emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/phps-mode da29937: Improved incremental lexer and other


From: Christian Johansson
Subject: [elpa] externals/phps-mode da29937: Improved incremental lexer and other optimizations
Date: Mon, 16 Sep 2019 11:39:37 -0400 (EDT)

branch: externals/phps-mode
commit da2993708413ad8799fc2474cadaef9d74098885
Author: Christian Johansson <address@hidden>
Commit: Christian Johansson <address@hidden>

    Improved incremental lexer and other optimizations
---
 README.md                      |   89 +-
 phps-mode-flycheck.el          |   39 -
 phps-mode-font-lock.el         |   39 -
 phps-mode-functions.el         |  410 ++++---
 phps-mode-lexer.el             | 2635 ++++++++++++++++++++++------------------
 phps-mode-macros.el            |   19 +
 phps-mode-map.el               |   38 -
 phps-mode-test-functions.el    |  107 +-
 phps-mode-test-integration.el  |  219 +++-
 phps-mode-test-lexer.el        |   18 +-
 phps-mode-test-syntax-table.el |    3 +-
 phps-mode-test.el              |   52 +-
 phps-mode.el                   |   78 +-
 13 files changed, 1979 insertions(+), 1767 deletions(-)

diff --git a/README.md b/README.md
index 9a9bd7a..6e3c254 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,9 @@
 [![License GPL 
3](https://img.shields.io/badge/license-GPL_3-green.svg)](https://www.gnu.org/licenses/gpl-3.0.txt)
 [![Build 
Status](https://travis-ci.org/cjohansson/emacs-phps-mode.svg?branch=master)](https://travis-ci.org/cjohansson/emacs-phps-mode)
 
-An Emacs major mode for PHP scripting language which aims at making a full 
semantic integration. Currently at *usable* stage.
+**Goal**: An Emacs major mode for PHP scripting language which aims at making 
a full semantic integration. Currently at *usable* stage.
 
-This mode does not require PHP installed on your computer because it has a 
built-in elisp based semantic lexer and semantic parser. It supports all PHP 
versions and Emacs >= 26.
+This mode does not require PHP installed on your computer because it has a 
built-in elisp based semantic lexer. It supports all PHP versions and Emacs >= 
26.
 
 ## Features
 
@@ -22,77 +22,15 @@ This mode does not require PHP installed on your computer 
because it has a built
 * Imenu support
 * Minimal mode map
 * Tested using unit tests and integration tests
-* Travis support
+* Continuous integration tests using Travis
 * Included in GNU ELPA package archive
+* A interactive function that can be used interactively to format buffers 
`(phps-mode-format-buffer)`
 
+## Keymap
 
-## Develop
-
-Make pull requests to develop branch or branches from develop branch. Tested 
changes are merged to master.
-
-## Tests
-
-If you have emacs at a customized location prefix the commands with your path, 
i.e.
-
-`export emacs="~/Documents/emacs/src/emacs" && make tests`
-
-Run all tests with `make tests`.
-
-### Functions
-
-Indentations, incremental processes, Imenu-support.
-
-``` bash
-make test-functions
-```
-
-### Integration
-
-This should test all other parts in collaboration.
-
-``` bash
-make test-integration
-```
-
-### Lexer
-
-Lexer token generation.
-
-``` bash
-make test-lexer
-```
-
-### Parser
-
-Semantic grammar. Not ready yet.
-
-``` bash
-make test-parser
-```
-
-### Syntax-table
-
-Basic point and region behaviour.
-
-``` bash
-make test-syntax-table
-```
-
-## Byte-compilation
-
-Plug-in should support byte-compilation and it is recommended.
-
-### Compile
-
-``` bash
-make compile
-```
-
-### Clean
-
-``` bash
-make clean
-```
+* `C-c /` Comment region
+* `C-c DEL` Uncomment region
+* `C-c C-r` Rescan buffer
 
 ## Installation
 
@@ -131,13 +69,10 @@ You can install via ELPA (`M-x package-install` + `RET` + 
`phps-mode` + `RET`),
 (add-to-list 'auto-mode-alist '("\\.\\(php\\|phtml\\)\\'" . phps-mode))
 ```
 
-## Contribute
-
-This project is licensed to Free Software Foundation so sign the needed 
papers. Then create a branch based on a updated `develop`. Make pull request.
-
-## Docs
+## Read more
 
-* [TODO](docs/todo.md)
+* [Development](docs/development.md)
 * [Heuristics](docs/heuristics.md)
-* [Imenu algorithm](docs/imenu.md)
 * [Indentation algorithm](docs/indentation.md)
+* [Imenu algorithm](docs/imenu.md)
+* [TODO](docs/todo.md)
diff --git a/phps-mode-flycheck.el b/phps-mode-flycheck.el
deleted file mode 100644
index 8216a46..0000000
--- a/phps-mode-flycheck.el
+++ /dev/null
@@ -1,39 +0,0 @@
-;;; phps-mode-flycheck.el --- Flycheck support for PHPs -*- lexical-binding: t 
-*-
-
-;; Copyright (C) 2017-2019  Free Software Foundation, Inc.
-
-;; This file is not part of GNU Emacs.
-
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2, or (at
-;; your option) any later version.
-
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
-
-
-;;; Commentary:
-
-;; Please see README.md from the same repository for extended documentation.
-
-
-;;; Code:
-
-(defun phps-mode-flycheck-init ()
-  "Add flycheck support for phps-mode."
-
-  (when (fboundp 'flycheck-add-mode)
-    (flycheck-add-mode 'php 'phps-mode)
-    (flycheck-add-mode 'php-phpmd 'phps-mode)
-    (flycheck-add-mode 'php-phpcs 'phps-mode)))
-
-
-(provide 'phps-mode-flycheck)
-
-;;; phps-mode-flycheck.el ends here
diff --git a/phps-mode-font-lock.el b/phps-mode-font-lock.el
deleted file mode 100644
index 59e0574..0000000
--- a/phps-mode-font-lock.el
+++ /dev/null
@@ -1,39 +0,0 @@
-;;; phps-mode-font-lock.el --- Font Lock for PHPs -*- lexical-binding: t -*-
-
-;; Copyright (C) 2017-2019  Free Software Foundation, Inc.
-
-;; This file is not part of GNU Emacs.
-
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2, or (at
-;; your option) any later version.
-
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
-
-
-;;; Commentary:
-
-;; Please see README.md from the same repository for extended documentation.
-
-
-;;; Code:
-
-(defun phps-mode-font-lock-init ()
-  "Apply font-lock."
-
-  (setq font-lock-keywords-only nil)
-
-  ;; This makes it possible to have full control over syntax coloring from the 
lexer
-  (set (make-local-variable 'font-lock-defaults) '(nil t))
-
-  )
-
-(provide 'phps-mode-font-lock)
-;;; phps-mode-font-lock.el ends here
diff --git a/phps-mode-functions.el b/phps-mode-functions.el
index 9a3c83d..92b04d6 100644
--- a/phps-mode-functions.el
+++ b/phps-mode-functions.el
@@ -26,42 +26,53 @@
 (require 'subr-x)
 (require 'phps-mode-lexer)
 
+(autoload 'phps-mode-runtime-debug-message "phps-mode")
+
+(require 'phps-mode-macros)
+
 (defvar phps-mode-functions-allow-after-change t
   "Flag to tell us whether after change detection is enabled or not.")
 
-(defvar phps-mode-functions-buffer-changes-start nil
-  "Start point of buffer changes, nil if none.")
+(defvar phps-mode-functions-buffer-changes nil
+  "A stack of buffer changes.")
 
-(defvar phps-mode-functions-lines-indent nil
-  "The indentation of each line in buffer, nil if none.")
+(defvar phps-mode-functions-idle-timer nil
+  "Timer object of idle timer.")
 
 (defvar phps-mode-functions-imenu nil
   "The Imenu alist for current buffer, nil if none.")
 
+(defvar phps-mode-functions-lines-indent nil
+  "The indentation of each line in buffer, nil if none.")
+
 (defvar phps-mode-functions-processed-buffer nil
   "Flag whether current buffer is processed or not.")
 
-(defvar phps-mode-functions-verbose nil
-  "Verbose messaging, default nil.")
+(defun phps-mode-functions-get-processed-buffer ()
+  "Get flag for whether buffer is processed or not."
+  phps-mode-functions-processed-buffer)
 
-(defun phps-mode-functions-get-buffer-changes-start ()
-  "Get buffer change start."
-  phps-mode-functions-buffer-changes-start)
-
-(defun phps-mode-functions-reset-buffer-changes-start ()
-  "Reset buffer change start."
-  ;; (message "Reset flag for buffer changes")
-  (setq phps-mode-functions-buffer-changes-start nil))
+(defun phps-mode-functions-reset-processed-buffer ()
+  "Reset flag for whether buffer is processed or not."
+  (setq-local phps-mode-functions-processed-buffer nil))
 
 (defun phps-mode-functions-process-current-buffer ()
-  "Process current buffer, generate indentations and Imenu."
-  ;; (message "(phps-mode-functions-process-current-buffer)")
-  (when (phps-mode-functions-get-buffer-changes-start)
-    (phps-mode-lexer-run-incremental)
-    (setq phps-mode-functions-processed-buffer nil))
-  (unless phps-mode-functions-processed-buffer
-    (phps-mode-functions--process-current-buffer)
-    (setq phps-mode-functions-processed-buffer t)))
+  "Process current buffer, generate indentations and Imenu, trigger 
incremental lexer if we have change."
+  (interactive)
+  (phps-mode-debug-message (message "Process current buffer"))
+  (when phps-mode-functions-idle-timer
+    (phps-mode-debug-message (message "Trigger incremental lexer"))
+    (phps-mode-lexer-run-incremental (current-buffer))
+    (setq-local phps-mode-functions-processed-buffer nil))
+  (if (not phps-mode-functions-processed-buffer)
+      (progn
+        (phps-mode-debug-message (message "Buffer is not processed"))
+        (let ((processed (phps-mode-functions--process-tokens-in-string 
phps-mode-lexer-tokens (buffer-substring-no-properties (point-min) 
(point-max)))))
+          (phps-mode-debug-message (message "Processed result: %s" processed))
+          (setq-local phps-mode-functions-imenu (nth 0 processed))
+          (setq-local phps-mode-functions-lines-indent (nth 1 processed)))
+        (setq-local phps-mode-functions-processed-buffer t))
+    (phps-mode-debug-message (message "Buffer is already processed"))))
 
 (defun phps-mode-functions-get-moved-lines-indent (old-lines-indents 
start-line-number diff)
   "Move OLD-LINES-INDENTS from START-LINE-NUMBER with DIFF points."
@@ -94,13 +105,13 @@
 (defun phps-mode-functions-move-imenu-index (start diff)
   "Moved imenu from START by DIFF points."
   (when phps-mode-functions-imenu
-    (setq phps-mode-functions-imenu (phps-mode-functions-get-moved-imenu 
phps-mode-functions-imenu start diff))))
+    (setq-local phps-mode-functions-imenu (phps-mode-functions-get-moved-imenu 
phps-mode-functions-imenu start diff))))
 
 (defun phps-mode-functions-move-lines-indent (start-line-number diff)
   "Move lines indent from START-LINE-NUMBER with DIFF points."
   (when phps-mode-functions-lines-indent
     ;; (message "Moving line-indent index from %s with %s" start-line-number 
diff)
-    (setq phps-mode-functions-lines-indent 
(phps-mode-functions-get-moved-lines-indent phps-mode-functions-lines-indent 
start-line-number diff))))
+    (setq-local phps-mode-functions-lines-indent 
(phps-mode-functions-get-moved-lines-indent phps-mode-functions-lines-indent 
start-line-number diff))))
   
 (defun phps-mode-functions-get-lines-indent ()
   "Return lines indent, process buffer if not done already."
@@ -126,14 +137,13 @@
           (let ((item-label (car item)))
             (if (listp (cdr item))
                 (let ((sub-item (phps-mode-functions-get-moved-imenu (cdr 
item) start diff)))
-                  (push `(,item-label . ,(nreverse sub-item)) new-index))
+                  (push `(,item-label . ,sub-item) new-index))
               (let ((item-start (cdr item)))
                 (when (>= item-start start)
                   (setq item-start (+ item-start diff)))
-                (push `(,item-label . ,item-start) new-index))))
-          )))
+                (push `(,item-label . ,item-start) new-index)))))))
 
-    new-index))
+    (nreverse new-index)))
 
 (defun phps-mode-functions--get-lines-in-buffer (beg end)
   "Return the number of lines in buffer between BEG and END."
@@ -150,10 +160,8 @@
 
 (defun phps-mode-functions--get-inline-html-indentation (inline-html indent 
tag-level curly-bracket-level square-bracket-level round-bracket-level)
   "Generate a list of indentation for each line in INLINE-HTML, working 
incrementally on INDENT, TAG-LEVEL, CURLY-BRACKET-LEVEL, SQUARE-BRACKET-LEVEL 
and ROUND-BRACKET-LEVEL."
-
-
-  (when phps-mode-functions-verbose
-    (message "Calculating HTML indent for: '%s'" inline-html))
+  (phps-mode-debug-message
+   (message "Calculating HTML indent for: '%s'" inline-html))
 
   ;; Add trailing newline if missing
   (unless (string-match "\n$" inline-html)
@@ -175,23 +183,22 @@
 
           (let ((temp-indent indent))
             (when first-object-is-nesting-decrease
-              (when phps-mode-functions-verbose
-                (message "Decreasing indent with one since first object was a 
nesting decrease"))
+              (phps-mode-debug-message
+               (message "Decreasing indent with one since first object was a 
nesting decrease"))
               (setq temp-indent (1- indent))
               (when (< temp-indent 0)
                 (setq temp-indent 0)))
             (push temp-indent line-indents))
 
           (setq indent-end (+ tag-level curly-bracket-level 
square-bracket-level round-bracket-level))
-          (when phps-mode-functions-verbose
-            (message "Encountered a new-line"))
+          (phps-mode-debug-message "Encountered a new-line")
           (if (> indent-end indent-start)
               (progn
-                (when phps-mode-functions-verbose
+                (phps-mode-debug-message
                   (message "Increasing indent since %s is above %s" indent-end 
indent-start))
                 (setq indent (1+ indent)))
             (when (< indent-end indent-start)
-              (when phps-mode-functions-verbose
+              (phps-mode-debug-message
                 (message "Decreasing indent since %s is below %s" indent-end 
indent-start))
               (setq indent (1- indent))
               (when (< indent 0)
@@ -229,22 +236,17 @@
             (setq first-object-on-line nil)
             (setq indent-end (+ tag-level curly-bracket-level 
square-bracket-level round-bracket-level))
             (when (< indent-end indent-start)
-              (when phps-mode-functions-verbose
-                (message "First object was nesting decrease"))
+              (phps-mode-debug-message "First object was nesting decrease")
               (setq first-object-is-nesting-decrease t))))
 
         (setq start end)))
     (list (nreverse line-indents) indent tag-level curly-bracket-level 
square-bracket-level round-bracket-level)))
 
-;; TODO Make this function support incremental process
-(defun phps-mode-functions--process-current-buffer ()
-  "Generate indexes for indentation and imenu for current buffer in one pass.  
Complexity: O(n)."
-  (if (boundp 'phps-mode-lexer-tokens)
-      (save-excursion
-        ;; (message "Processing current buffer")
-        (goto-char (point-min))
-        (when phps-mode-functions-verbose
-          (message "\nCalculation indentation for all lines in buffer:\n\n%s" 
(buffer-substring-no-properties (point-min) (point-max))))
+(defun phps-mode-functions--process-tokens-in-string (tokens string)
+  "Generate indexes for imenu and indentation for TOKENS and STRING one pass.  
Complexity: O(n)."
+  (if tokens
+      (progn
+        (phps-mode-debug-message (message "\nCalculation indentation and imenu 
for all lines in buffer:\n\n%s" string))
         (let ((in-heredoc nil)
               (in-heredoc-started-this-line nil)
               (in-heredoc-ended-this-line nil)
@@ -302,7 +304,7 @@
               (token-end nil)
               (token-start-line-number 0)
               (token-end-line-number 0)
-              (tokens (nreverse (copy-sequence phps-mode-lexer-tokens)))
+              (tokens (nreverse (copy-sequence tokens)))
               (nesting-stack nil)
               (nesting-key nil)
               (class-declaration-started-this-line nil)
@@ -325,7 +327,7 @@
               (imenu-nesting-level 0)
               (incremental-line-number 1))
 
-          (push `(END_PARSE ,(point-max) . ,(point-max)) tokens)
+          (push `(END_PARSE ,(length string) . ,(length string)) tokens)
 
           ;; Iterate through all buffer tokens from beginning to end
           (dolist (item (nreverse tokens))
@@ -336,9 +338,10 @@
                   (next-token-start-line-number nil)
                   (next-token-end-line-number nil))
 
-              (when token
+              (when (and token
+                         (< token-end next-token-start))
                 ;; NOTE We use a incremental-line-number calculation because 
`line-at-pos' takes a lot of time
-                (setq incremental-line-number (+ incremental-line-number 
(phps-mode-functions--get-lines-in-buffer token-end next-token-start))))
+                (setq incremental-line-number (+ incremental-line-number 
(phps-mode-functions--get-lines-in-string (substring string (1- token-end) (1- 
next-token-start))))))
 
               ;; Handle the pseudo-token for last-line
               (if (equal next-token 'END_PARSE)
@@ -348,9 +351,10 @@
                 (setq next-token-start-line-number incremental-line-number)
 
                 ;; NOTE We use a incremental-line-number calculation because 
`line-at-pos' takes a lot of time
-                (setq incremental-line-number (+ incremental-line-number 
(phps-mode-functions--get-lines-in-buffer next-token-start next-token-end)))
+                ;; (message "Lines for %s '%s'" next-token (substring string 
(1- next-token-start) (1- next-token-end)))
+                (setq incremental-line-number (+ incremental-line-number 
(phps-mode-functions--get-lines-in-string (substring string (1- 
next-token-start) (1- next-token-end)))))
                 (setq next-token-end-line-number incremental-line-number)
-                (when phps-mode-functions-verbose
+                (phps-mode-debug-message
                   (message "Token '%s' pos: %s-%s lines: %s-%s" next-token 
next-token-start next-token-end next-token-start-line-number 
next-token-end-line-number)))
 
               ;; Token logic - we have one-two token look-ahead at this point
@@ -410,7 +414,7 @@
 
                     ((and (or (equal token 'T_STRING)
                               (equal token 'T_NS_SEPARATOR))
-                          (setq imenu-in-namespace-name (concat 
imenu-in-namespace-name (buffer-substring-no-properties token-start 
token-end)))))))
+                          (setq imenu-in-namespace-name (concat 
imenu-in-namespace-name (substring string (1- token-start) (1- token-end))))))))
 
                  (imenu-in-class-declaration
                   (cond
@@ -422,24 +426,25 @@
 
                    ((and (equal token 'T_STRING)
                          (not imenu-in-class-name))
-                    (setq imenu-in-class-name (buffer-substring-no-properties 
token-start token-end)))))
+                    (setq imenu-in-class-name (substring string (1- 
token-start) (1- token-end))))))
 
                  (imenu-in-function-declaration
                   (cond
 
                    ((or (string= token "{")
                         (string= token ";"))
-                    (if imenu-in-class-name
-                        (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-class-index)
-                      (if imenu-in-namespace-name
-                          (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-namespace-index)
-                        (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-index)))
+                    (when imenu-in-function-name
+                      (if imenu-in-class-name
+                          (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-class-index)
+                        (if imenu-in-namespace-name
+                            (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-namespace-index)
+                          (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-index))))
                     (setq imenu-in-function-name nil)
                     (setq imenu-in-function-declaration nil))
 
                    ((and (equal token 'T_STRING)
                          (not imenu-in-function-name))
-                    (setq imenu-in-function-name 
(buffer-substring-no-properties token-start token-end))
+                    (setq imenu-in-function-name (substring string (1- 
token-start) (1- token-end)))
                     (setq imenu-in-function-index token-start))))
 
                  (t (cond
@@ -450,7 +455,8 @@
                       (setq imenu-in-namespace-declaration t))
 
                      ((and (not imenu-in-class-name)
-                           (equal token 'T_CLASS))
+                           (or (equal token 'T_CLASS)
+                               (equal token 'T_INTERFACE)))
                       (setq imenu-in-class-name nil)
                       (setq imenu-in-class-declaration t))
 
@@ -484,10 +490,10 @@
                   (when first-token-on-line
                     (setq first-token-is-inline-html t))
 
-                  (let ((inline-html-indents 
(phps-mode-functions--get-inline-html-indentation 
(buffer-substring-no-properties token-start token-end) inline-html-indent 
inline-html-tag-level inline-html-curly-bracket-level 
inline-html-square-bracket-level inline-html-round-bracket-level)))
+                  (let ((inline-html-indents 
(phps-mode-functions--get-inline-html-indentation (substring string (1- 
token-start) (1- token-end)) inline-html-indent inline-html-tag-level 
inline-html-curly-bracket-level inline-html-square-bracket-level 
inline-html-round-bracket-level)))
 
-                    (when phps-mode-functions-verbose
-                      (message "Received inline html indent: %s from inline 
HTML: '%s'" inline-html-indents (buffer-substring-no-properties token-start 
token-end)))
+                    (phps-mode-debug-message
+                      (message "Received inline html indent: %s from inline 
HTML: '%s'" inline-html-indents (substring string (1- token-start) (1- 
token-end))))
 
                     ;; Update indexes
                     (setq inline-html-indent (nth 1 inline-html-indents))
@@ -498,7 +504,7 @@
 
                     ;; Does token span several lines and is it not only 
white-space?
                     (when (> token-end-line-number token-start-line-number)
-                      (unless (string= (string-trim 
(buffer-substring-no-properties token-start token-end)) "")
+                      (unless (string= (string-trim (substring string (1- 
token-start) (1- token-end))) "")
                         (let ((token-line-number-diff token-start-line-number))
                           ;; Iterate lines here and add indents
                           (dolist (item (nth 0 inline-html-indents))
@@ -506,7 +512,7 @@
                             (when (or (not (= token-line-number-diff 
token-start-line-number))
                                       first-token-is-inline-html)
                               (puthash token-line-number-diff (list item 0) 
line-indents)
-                              (when phps-mode-functions-verbose
+                              (phps-mode-debug-message
                                 (message "Putting indent at line %s to %s from 
inline HTML" token-line-number-diff item)))
                             (setq token-line-number-diff (1+ 
token-line-number-diff))))))))
 
@@ -547,7 +553,7 @@
                   (when (and switch-curly-stack
                              (= (1+ curly-bracket-level) (car 
switch-curly-stack)))
 
-                    (when phps-mode-functions-verbose
+                    (phps-mode-debug-message
                       (message "Ended switch curly stack at %s" 
curly-bracket-level))
 
                     (setq allow-custom-column-decrement t)
@@ -570,7 +576,7 @@
                   (when (and (equal token 'T_ENDSWITCH)
                              switch-case-alternative-stack)
 
-                    (when phps-mode-functions-verbose
+                    (phps-mode-debug-message
                       (message "Ended alternative switch stack at %s" 
alternative-control-structure-level))
                     
                     (pop switch-alternative-stack)
@@ -598,7 +604,7 @@
                         ;; Save curly bracket level when switch starts
                         (when (equal after-special-control-structure-token 
'T_SWITCH)
 
-                          (when phps-mode-functions-verbose
+                          (phps-mode-debug-message
                             (message "Started switch curly stack at %s" 
curly-bracket-level))
 
                           (push curly-bracket-level switch-curly-stack))
@@ -611,20 +617,20 @@
                             ;; Save alternative nesting level for switch
                             (when (equal after-special-control-structure-token 
'T_SWITCH)
 
-                              (when phps-mode-functions-verbose
+                              (phps-mode-debug-message
                                 (message "Started switch alternative stack at 
%s" alternative-control-structure-level))
 
                               (push alternative-control-structure-level 
switch-alternative-stack))
 
                             (setq alternative-control-structure-level (1+ 
alternative-control-structure-level))
 
-                            (when phps-mode-functions-verbose
+                            (phps-mode-debug-message
                               (message "\nIncreasing 
alternative-control-structure after %s %s to %s\n" 
after-special-control-structure-token token 
alternative-control-structure-level))
                             )
 
                         ;; Don't start inline control structures after a while 
($condition); expression
                         (unless (string= token ";")
-                          (when phps-mode-functions-verbose
+                          (phps-mode-debug-message
                             (message "\nStarted inline control-structure after 
%s at %s\n" after-special-control-structure-token token))
 
                           (setq in-inline-control-structure t)
@@ -651,8 +657,7 @@
                                    (= square-bracket-level (car 
in-concatenation-square-bracket-level)))
                               (and (string= token"]")
                                    (< square-bracket-level (car 
in-concatenation-square-bracket-level))))
-                      (when phps-mode-functions-verbose
-                        (message "Ended concatenation"))
+                      (phps-mode-debug-message "Ended concatenation")
                       (pop in-concatenation-round-bracket-level)
                       (pop in-concatenation-square-bracket-level)
                       (unless in-concatenation-round-bracket-level
@@ -661,8 +666,7 @@
                   (when (and (> next-token-start-line-number 
token-end-line-number)
                              (or (string= token ".")
                                  (string= next-token ".")))
-                    (when phps-mode-functions-verbose
-                      (message "Started concatenation"))
+                    (phps-mode-debug-message "Started concatenation")
                     (setq in-concatenation t)
                     (push round-bracket-level 
in-concatenation-round-bracket-level)
                     (push square-bracket-level 
in-concatenation-square-bracket-level)
@@ -706,7 +710,7 @@
                     (when first-token-on-line
                       (setq first-token-is-nesting-decrease t))
 
-                    (when phps-mode-functions-verbose
+                    (phps-mode-debug-message
                       (message "\nDecreasing alternative control structure 
nesting at %s to %s\n" token alternative-control-structure-level)))
 
                   )
@@ -736,7 +740,7 @@
 
                     ;; NOTE Ending an assignment because of a T_FUNCTION token 
is to support PSR-2 Closures
                     
-                    (when phps-mode-functions-verbose
+                    (phps-mode-debug-message
                       (message "Ended assignment %s at %s %s" 
in-assignment-level token next-token))
                     (pop in-assignment-square-bracket-level)
                     (pop in-assignment-round-bracket-level)
@@ -752,7 +756,7 @@
                            (= square-bracket-level (car 
in-assignment-square-bracket-level))
                            (or (string= next-token ")")
                                (string= next-token "]")))
-                      (when phps-mode-functions-verbose
+                      (phps-mode-debug-message
                         (message "Ended another assignment %s at %s %s" 
in-assignment-level token next-token))
                       (pop in-assignment-square-bracket-level)
                       (pop in-assignment-round-bracket-level)
@@ -778,8 +782,7 @@
                                (equal token 'T_OR_EQUAL)
                                (equal token 'T_XOR_EQUAL)
                                (equal token 'T_COALESCE_EQUAL)))
-                  (when phps-mode-functions-verbose
-                    (message "Started assignment"))
+                  (phps-mode-debug-message "Started assignment")
                   (setq in-assignment t)
                   (push round-bracket-level in-assignment-round-bracket-level)
                   (push square-bracket-level 
in-assignment-square-bracket-level)
@@ -795,7 +798,7 @@
                        (not (or
                              (equal next-token 'T_OBJECT_OPERATOR)
                              (equal next-token 'T_PAAMAYIM_NEKUDOTAYIM))))
-                  (when phps-mode-functions-verbose
+                  (phps-mode-debug-message
                     (message "Ended object-operator at %s %s at level %s" 
token next-token in-object-operator-level))
                   (pop in-object-operator-round-bracket-level)
                   (pop in-object-operator-square-bracket-level)
@@ -808,7 +811,7 @@
                   (when (or (equal next-token 'T_STRING)
                             (string= next-token "("))
                     (progn
-                      (when phps-mode-functions-verbose
+                      (phps-mode-debug-message
                         (message "Started object-operator at %s %s on level 
%s"  token next-token in-object-operator-level))
                       (push round-bracket-level 
in-object-operator-round-bracket-level)
                       (push square-bracket-level 
in-object-operator-square-bracket-level)
@@ -820,7 +823,7 @@
                 (when (and (or (equal token 'T_OBJECT_OPERATOR)
                                (equal token 'T_PAAMAYIM_NEKUDOTAYIM))
                            (equal next-token 'T_STRING))
-                  (when phps-mode-functions-verbose
+                  (phps-mode-debug-message
                     (message "After object-operator at %s level %s"  token 
in-object-operator-level))
                   (setq after-object-operator t))
 
@@ -829,15 +832,13 @@
                   (when (and (string= token ";")
                              (= curly-bracket-level (car 
in-return-curly-bracket-level)))
 
-                    (when phps-mode-functions-verbose
-                      (message "Ended return at %s" token))
+                    (phps-mode-debug-message (message "Ended return at %s" 
token))
                     (pop in-return-curly-bracket-level)
                     (unless in-return-curly-bracket-level
                       (setq in-return nil))
                     (setq in-return-level (1- in-return-level))))
                 (when (equal token 'T_RETURN)
-                  (when phps-mode-functions-verbose
-                    (message "Started return"))
+                  (phps-mode-debug-message "Started return")
                   (setq in-return t)
                   (push curly-bracket-level in-return-curly-bracket-level)
                   (setq in-return-level (1+ in-return-level)))
@@ -851,7 +852,7 @@
                   (when (and switch-case-alternative-stack
                              (= (1- alternative-control-structure-level) (car 
switch-case-alternative-stack)))
 
-                    (when phps-mode-functions-verbose
+                    (phps-mode-debug-message
                       (message "Found CASE %s vs %s" (1- 
alternative-control-structure-level) (car switch-case-alternative-stack)))
 
                     (setq alternative-control-structure-level (1- 
alternative-control-structure-level))
@@ -863,8 +864,7 @@
 
               (when token
 
-                (when phps-mode-functions-verbose
-                  (message "Processing token: %s" token))
+                (phps-mode-debug-message (message "Processing token: %s" 
token))
                 
                 ;; Calculate nesting
                 (setq nesting-end (+ round-bracket-level square-bracket-level 
curly-bracket-level alternative-control-structure-level in-assignment-level 
in-class-declaration-level in-concatenation-level in-return-level 
in-object-operator-level))
@@ -885,7 +885,7 @@
                     ;; Handle case were nesting has decreased less than next 
as well
                     (while (and nesting-stack
                                 (<= nesting-end (car (car nesting-stack))))
-                      (when phps-mode-functions-verbose
+                      (phps-mode-debug-message
                         (message "\nPopping %s from nesting-stack since %s is 
lesser or equal to %s, next value is: %s\n" (car nesting-stack) nesting-end 
(car (car nesting-stack)) (nth 1 nesting-stack)))
                       (pop nesting-stack)
                       (setq nesting-decrement (1+ nesting-decrement)))
@@ -896,11 +896,11 @@
                           ;; Decrement column
                           (if allow-custom-column-decrement
                               (progn
-                                (when phps-mode-functions-verbose
+                                (phps-mode-debug-message
                                   (message "Doing custom decrement 1 from %s 
to %s" column-level (- column-level (- nesting-start nesting-end))))
                                 (setq column-level (- column-level (- 
nesting-start nesting-end)))
                                 (setq allow-custom-column-decrement nil))
-                            (when phps-mode-functions-verbose
+                            (phps-mode-debug-message
                               (message "Doing regular decrement 1 from %s to 
%s" column-level (1- column-level)))
                             (setq column-level (- column-level 
nesting-decrement)))
 
@@ -909,14 +909,14 @@
                             (setq column-level 0)))
 
                       (unless temp-post-indent
-                        (when phps-mode-functions-verbose
+                        (phps-mode-debug-message
                           (message "Temporary setting post indent %s" 
column-level))
                         (setq temp-post-indent column-level))
 
                       ;; Decrement column
                       (if allow-custom-column-decrement
                           (progn
-                            (when phps-mode-functions-verbose
+                            (phps-mode-debug-message
                               (message "Doing custom decrement 2 from %s to 
%s" column-level (- column-level (- nesting-start nesting-end))))
                             (setq temp-post-indent (- temp-post-indent (- 
nesting-start nesting-end)))
                             (setq allow-custom-column-decrement nil))
@@ -955,7 +955,7 @@
                         (setq column-level-start inline-html-indent))
 
                       ;; Save line indent
-                      (when phps-mode-functions-verbose
+                      (phps-mode-debug-message
                         (message "Process line ending. nesting: %s-%s, 
line-number: %s-%s,     indent: %s.%s,  token: %s" nesting-start nesting-end 
token-start-line-number token-end-line-number column-level-start tuning-level 
token))
 
                       (when (> token-start-line-number 0)
@@ -981,13 +981,10 @@
                                 (setq allow-custom-column-increment nil))
                             (setq column-level (1+ column-level)))
 
-                          (when phps-mode-functions-verbose
+                          (phps-mode-debug-message
                             (message "\nPushing (%s %s %s %s) to nesting-stack 
since %s is greater than %s or stack is empty\n" nesting-start nesting-end 
nesting-key token nesting-end (car (cdr (car nesting-stack))))
                             )
-                          (push `(,nesting-stack-end ,nesting-end ,nesting-key 
,token) nesting-stack)
-                          (when phps-mode-functions-verbose
-                            ;; (message "New stack %s, start: %s end: %s\n" 
nesting-stack (car (car nesting-stack)) (car (cdr (car nesting-stack))))
-                            )))
+                          (push `(,nesting-stack-end ,nesting-end ,nesting-key 
,token) nesting-stack)))
 
 
                       ;; Does token span over several lines and is it not a 
INLINE_HTML token?
@@ -1020,7 +1017,7 @@
                       (when (and (> next-token-start-line-number (1+ 
token-end-line-number))
                                  (not (equal token 'T_CLOSE_TAG)))
 
-                        (when phps-mode-functions-verbose
+                        (phps-mode-debug-message
                           (message "\nDetected token-less lines between %s and 
%s, should have indent: %s\n" token-end-line-number 
next-token-start-line-number column-level))
 
                         (let ((token-line-number-diff (1- (- 
next-token-start-line-number token-end-line-number))))
@@ -1067,99 +1064,122 @@
               (setq token-start-line-number next-token-start-line-number)
               (setq token-end-line-number next-token-end-line-number)
               (setq token-number (1+ token-number))))
-          (setq phps-mode-functions-imenu (nreverse imenu-index))
-          (setq phps-mode-functions-lines-indent line-indents)))
-    (setq phps-mode-functions-imenu nil)
-    (setq phps-mode-functions-lines-indent nil)))
-
-(defun phps-mode-functions-around-newline (old-function &rest arguments)
-  "Call OLD-FUNCTION with ARGUMENTS and then shift indexes if the rest of the 
line is just white-space."
-  (if (string= major-mode "phps-mode")
-      (progn
-        ;; (message "Running advice")
-        (let ((old-pos (point))
-              (looking-at-whitespace (looking-at-p "[\ \n\t\r]*\n"))
-              (old-line-number (line-number-at-pos)))
-
-          (if looking-at-whitespace
-              (progn
-                ;; (message "Looking at white-space")
-
-                ;; Temporarily disable change detection to not trigger 
incremental lexer
-
-                ;; We move indexes before calling old-function
-                ;; because old-function could be `newline-and-indent'
-                ;; and this would trigger `indent-line'
-                ;; which will trigger processing buffer
-                (phps-mode-lexer-move-tokens old-pos 1)
-                (phps-mode-lexer-move-states old-pos 1)
-                (phps-mode-functions-move-imenu-index old-pos 1)
-                (phps-mode-functions-move-lines-indent old-line-number 1)
-
-                (setq phps-mode-functions-allow-after-change nil)
-                (apply old-function arguments)
-                (setq phps-mode-functions-allow-after-change t))
-
-            (apply old-function arguments)
-            ;; (message "Not looking at white-space")
-            )))
-    (apply old-function arguments)))
+          (list (nreverse imenu-index) line-indents)))
+    (list nil nil)))
 
+;; TODO newline with electric mode not working
 (defun phps-mode-functions-indent-line ()
   "Indent line."
+  (phps-mode-runtime-debug-message "Indent line")
+  (phps-mode-debug-message (message "Indent line"))
   (phps-mode-functions-process-current-buffer)
-  (when phps-mode-functions-lines-indent
-    (let ((indent (gethash (line-number-at-pos (point)) 
phps-mode-functions-lines-indent)))
-      (when indent
-        ;; (message "indent: %s %s %s" indent (car indent) (car (cdr indent)))
-        (let ((indent-sum (+ (* (car indent) tab-width) (car (cdr indent))))
-              (current-indentation (current-indentation))
-              (line-start (line-beginning-position)))
-
-          (unless current-indentation
-            (setq current-indentation 0))
-
-          ;; Only continue if current indentation is wrong
-          (unless (equal indent-sum current-indentation)
-            (let ((indent-diff (- indent-sum current-indentation)))
-              ;; (message "Indenting to %s current column %s" indent-sum 
(current-indentation))
-              ;; (message "inside scripting, start: %s, end: %s, indenting to 
column %s " start end indent-level)
-
-              (indent-line-to indent-sum)
-
-
-              ;; When indent is changed the trailing tokens and states just 
need to adjust their positions, this will improve speed of indent-region a lot
-              (phps-mode-lexer-move-tokens line-start indent-diff)
-              (phps-mode-lexer-move-states line-start indent-diff)
-              (phps-mode-functions-move-imenu-index line-start indent-diff)
-
-              ;; (message "Diff after indent at %s is %s" line-start 
indent-diff)
-
-              ;; Reset change flag
-              (phps-mode-functions-reset-buffer-changes-start)
-
-              )))))))
-
-;; TODO Consider how indentation and imenu-index should be affected by this
-(defun phps-mode-functions-after-change (start _stop _length)
-  "Track buffer change from START to STOP with length LENGTH."
-  (when phps-mode-functions-allow-after-change
-
-    ;; If we haven't scheduled incremental lexer before - do it
-    (when (and (not phps-mode-functions-buffer-changes-start)
-               (boundp 'phps-mode-idle-interval)
-               phps-mode-idle-interval)
-      ;; (message "Enqueued incremental lexer")
-      (run-with-idle-timer phps-mode-idle-interval nil 
#'phps-mode-lexer-run-incremental))
-
-    ;; When point of change is not set or when start of new changes precedes 
old change - update the point
-    (when (or (not phps-mode-functions-buffer-changes-start)
-              (< start phps-mode-functions-buffer-changes-start))
-      (setq phps-mode-functions-buffer-changes-start start)
-      ;; (message "Setting start of changes to: %s-%s" 
phps-mode-functions-buffer-changes-start stop))
-
-      ;; (message "phps-mode-functions-after-change %s %s %s" start stop 
length)
-      )))
+  (if phps-mode-functions-lines-indent
+      (let ((line-number (line-number-at-pos (point))))
+        (phps-mode-runtime-debug-message "Found lines indent index, 
indenting..")
+        (phps-mode-debug-message (message "Found lines indent index, 
indenting.."))
+        (let ((indent (gethash line-number phps-mode-functions-lines-indent)))
+          (if indent
+              (progn
+                (phps-mode-runtime-debug-message (format "Found indent for 
line number %s = %s" line-number indent))
+                (let ((indent-sum (+ (* (car indent) tab-width) (car (cdr 
indent))))
+                      (old-indentation (current-indentation))
+                      (line-start (line-beginning-position)))
+
+                  (unless old-indentation
+                    (setq old-indentation 0))
+
+                  ;; Only continue if current indentation is wrong
+                  (if (not (equal indent-sum old-indentation))
+                      (progn
+                        (phps-mode-runtime-debug-message (format "Indenting 
line since it's not already indented correctly %s vs %s" old-indentation 
indent-sum))
+
+                        (setq-local phps-mode-functions-allow-after-change nil)
+                        (indent-line-to indent-sum)
+                        (setq-local phps-mode-functions-allow-after-change t)
+
+                        (let ((indent-diff (- (current-indentation) 
old-indentation)))
+
+                          (phps-mode-runtime-debug-message (format "Moving 
indexes by %s points from %s" indent-diff line-start))
+                          (phps-mode-runtime-debug-message (format "Lexer 
tokens before move: %s" phps-mode-lexer-tokens))
+
+                          ;; When indent is changed the trailing tokens and 
states just need to adjust their positions, this will improve speed of 
indent-region a lot
+                          (phps-mode-lexer-move-tokens line-start indent-diff)
+                          (phps-mode-lexer-move-states line-start indent-diff)
+                          (phps-mode-functions-move-imenu-index line-start 
indent-diff)
+
+                          (phps-mode-runtime-debug-message (format "Lexer 
tokens after move: %s" phps-mode-lexer-tokens))
+                          (phps-mode-debug-message
+                           (message "Lexer tokens after move: %s" 
phps-mode-lexer-tokens)
+                           (message "Lexer states after move: %s" 
phps-mode-lexer-states))
+
+                          ;; Reset change flag
+                          (phps-mode-functions--reset-changes)
+                          (phps-mode-functions--cancel-idle-timer)
+
+                          ;; Update last buffer states
+                          (setq-local phps-mode-lexer-buffer-length (1- 
(point-max)))
+                          (setq-local phps-mode-lexer-buffer-contents 
(buffer-substring-no-properties (point-min) (point-max)))
+
+                          (phps-mode-runtime-debug-message (format "buffer 
contents:\n%s" (buffer-substring-no-properties (point-min) (point-max))))
+                          ))
+                    (phps-mode-runtime-debug-message "Skipping indentation of 
line since it's already indented correctly"))))
+            (phps-mode-runtime-debug-message (format "Found no indent for line 
number %s" line-number)))))
+    (phps-mode-runtime-debug-message "Did not find lines indent index, 
skipping indenting..")
+    (phps-mode-debug-message "Did not find lines indent index, skipping 
indenting..")
+    (message "Did not find lines indent index, skipping indenting..")))
+
+(defun phps-mode-functions--reset-changes ()
+  "Reset change stack."
+  (setq-local phps-mode-functions-buffer-changes nil))
+
+(defun phps-mode-functions--get-changes ()
+  "Get change stack."
+  phps-mode-functions-buffer-changes)
+
+(defun phps-mode-functions--cancel-idle-timer ()
+  "Cancel idle timer."
+  (phps-mode-runtime-debug-message "Cancelled idle timer")
+  (phps-mode-debug-message (message "Cancelled idle timer"))
+  (when phps-mode-functions-idle-timer
+    (cancel-timer phps-mode-functions-idle-timer)
+    (setq-local phps-mode-functions-idle-timer nil)))
+
+(defun phps-mode-functions--start-idle-timer ()
+  "Start idle timer."
+  (phps-mode-runtime-debug-message "Enqueued idle timer")
+  (phps-mode-debug-message (message "Enqueued idle timer"))
+  (when (boundp 'phps-mode-idle-interval)
+    (setq-local phps-mode-functions-idle-timer (run-with-idle-timer 
phps-mode-idle-interval nil #'phps-mode-lexer-run-incremental 
(current-buffer)))))
+
+(defun phps-mode-functions-after-change (start stop length)
+  "Track buffer change from START to STOP with LENGTH."
+  (phps-mode-runtime-debug-message
+   (format "After change %s - %s, length: %s" start stop length))
+  (phps-mode-debug-message
+   (message "After change %s - %s, length: %s" start stop length))
+
+  (if phps-mode-functions-allow-after-change
+      (progn
+        (phps-mode-debug-message (message "After change registration is 
enabled"))
+        (phps-mode-runtime-debug-message "After change registration is 
enabled")
+        
+        ;; If we haven't scheduled incremental lexer before - do it
+        (when (and (boundp 'phps-mode-idle-interval)
+                   phps-mode-idle-interval
+                   (not phps-mode-functions-idle-timer))
+
+          ;; Reset imenu
+          (when (and (boundp 'imenu--index-alist)
+                     imenu--index-alist)
+            (setq-local imenu--index-alist nil)
+            (phps-mode-debug-message (message "Cleared Imenu index")))
+
+          (phps-mode-functions--start-idle-timer))
+
+        ;; Save change in changes stack
+        (push `(,start ,stop ,length ,(point-max) 
,(buffer-substring-no-properties (point-min) (point-max))) 
phps-mode-functions-buffer-changes))
+    (phps-mode-debug-message (message "After change registration is disabled"))
+    (phps-mode-runtime-debug-message "After change registration is disabled")))
 
 (defun phps-mode-functions-imenu-create-index ()
   "Get Imenu for current buffer."
diff --git a/phps-mode-lexer.el b/phps-mode-lexer.el
index de7a097..be94a6d 100644
--- a/phps-mode-lexer.el
+++ b/phps-mode-lexer.el
@@ -30,8 +30,13 @@
 ;;; Code:
 
 ;; NOTE We use autoload here to circumvent recursive require
-(autoload 'phps-mode-functions-get-buffer-changes-start "phps-mode-functions")
-(autoload 'phps-mode-functions-reset-buffer-changes-start 
"phps-mode-functions")
+(autoload 'phps-mode-functions--reset-changes "phps-mode-functions")
+(autoload 'phps-mode-functions--cancel-idle-timer "phps-mode-functions")
+(autoload 'phps-mode-functions--get-changes "phps-mode-functions")
+(autoload 'phps-mode-get-syntax-table "phps-mode")
+(autoload 'phps-mode-functions-processed-buffer "phps-mode-functions")
+(autoload 'phps-mode-functions-reset-processed-buffer "phps-mode-functions")
+(autoload 'phps-mode-runtime-debug-message "phps-mode")
 
 (require 'semantic)
 (require 'semantic/lex)
@@ -39,6 +44,8 @@
 ;; NOTE This line is required to pass byte-compilation
 (require 'semantic/wisent)
 
+(require 'phps-mode-macros)
+
 
 ;; Fix for byte-compilation warnings
 
@@ -54,6 +61,12 @@
 (defvar phps-mode-lexer-states nil
   "A list of lists containing start, state and state stack.")
 
+(defvar phps-mode-lexer-buffer-length nil
+  "Length of lexed buffer.")
+
+(defvar phps-mode-lexer-buffer-contents nil
+  "Contents of lexed buffer.")
+
 
 ;; SETTINGS
 
@@ -81,12 +94,12 @@
 (defvar phps-mode-lexer-STATE nil
   "Current state.")
 
-(defvar phps-mode-lexer-EXPECTED nil
-  "Flag whether something is expected or not.")
-
 (defvar phps-mode-lexer-state_stack nil
   "Stack of states.")
 
+(defvar phps-mode-lexer-EXPECTED nil
+  "Flag whether something is expected or not.")
+
 (defvar phps-mode-lexer-heredoc_label_stack (list)
   "The current heredoc_label.")
 
@@ -172,9 +185,8 @@
 
 (defun phps-mode-lexer-BEGIN (state)
   "Begin STATE."
-  (setq phps-mode-lexer-STATE state)
   ;; (message "Begun state %s" state)
-  )
+  (setq-local phps-mode-lexer-STATE state))
 
 ;; _yy_push_state
 (defun phps-mode-lexer-yy_push_state (new-state)
@@ -189,8 +201,7 @@
     ;; (message "Going back to poppped state %s" old-state)
     (if old-state
         (phps-mode-lexer-BEGIN old-state)
-      (display-warning "phps-mode" "PHPs Lexer Error - Going back to nil?"))
-    ))
+      (display-warning 'phps-mode "PHPs Lexer Error - Going back to nil?"))))
 
 (defun phps-mode-lexer-MOVE_FORWARD (position)
   "Move forward to POSITION."
@@ -450,1131 +461,1138 @@
 (define-lex-analyzer phps-mode-lexer-lex-analyzer
   "Elisp port of original Zend re2c lexer."
   t
-  (let ((old-start (point))
-        (heredoc_label (car phps-mode-lexer-heredoc_label_stack))
-        (ST_IN_SCRIPTING (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_IN_SCRIPTING))
-        (ST_INITIAL (= phps-mode-lexer-STATE phps-mode-lexer-ST_INITIAL))
-        (ST_LOOKING_FOR_PROPERTY (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_LOOKING_FOR_PROPERTY))
-        (ST_DOUBLE_QUOTES (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_DOUBLE_QUOTES))
-        (ST_BACKQUOTE (= phps-mode-lexer-STATE phps-mode-lexer-ST_BACKQUOTE))
-        (ST_HEREDOC (= phps-mode-lexer-STATE phps-mode-lexer-ST_HEREDOC))
-        (ST_NOWDOC (= phps-mode-lexer-STATE phps-mode-lexer-ST_NOWDOC))
-        (ST_LOOKING_FOR_VARNAME (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_LOOKING_FOR_VARNAME))
-        (ST_END_HEREDOC (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_END_HEREDOC))
-        (ST_VAR_OFFSET (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_VAR_OFFSET)))
-
-    ;; Reset re2c flags
-    (setq phps-mode-lexer-re2c-matching-body nil)
-    (setq phps-mode-lexer-re2c-matching-length nil)
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "exit"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_EXIT (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "die" ))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_DIE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "function"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_FUNCTION (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "const"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_CONST (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "return"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_RETURN (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at (concat "yield" 
phps-mode-lexer-WHITESPACE "from" "[^a-zA-Z0-9_\x80-\xff]")))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_YIELD_FROM (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "yield"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_YIELD (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "try"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_TRY (match-beginning 0) (match-end 
0))))0
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "catch"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_CATCH (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "finally"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_FINALLY (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "throw"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_THROW (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "if"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_IF (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "elseif"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ELSEIF (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "endif"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ENDIF (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "else"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ELSE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "while"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_WHILE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "endwhile"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ENDWHILE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "do"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_DO (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "for"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_FOR (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "endfor"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ENDFOR (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "foreach"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_FOREACH (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "endforeach"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ENDFOREACH (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "declare"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_DECLARE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "enddeclare"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ENDDECLARE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "instanceof"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_INSTANCEOF (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "as"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_AS (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "switch"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_SWITCH (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "endswitch"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ENDSWITCH (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "case"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_CASE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "default"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_DEFAULT (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "break"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_BREAK (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "continue"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_CONTINUE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "goto"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_GOTO (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "echo"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ECHO (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "print"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_PRINT (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "class"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_CLASS (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "interface"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_INTERFACE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "trait"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_TRAIT (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "extends"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_EXTENDS (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "implements"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_IMPLEMENTS (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "->"))
-     (lambda()
-       (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_LOOKING_FOR_PROPERTY)
-       (phps-mode-lexer-RETURN_TOKEN 'T_OBJECT_OPERATOR (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and (or ST_IN_SCRIPTING ST_LOOKING_FOR_PROPERTY)
-          (looking-at phps-mode-lexer-WHITESPACE))
-     (lambda()
-       (let* ((start (match-beginning 0))
-              (end (match-end 0))
-              (data (buffer-substring-no-properties start end)))
-         (if phps-mode-lexer-PARSER_MODE
-             (phps-mode-lexer-MOVE_FORWARD end)
-           (phps-mode-lexer-RETURN_TOKEN data start end)))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_LOOKING_FOR_PROPERTY (looking-at "->"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_OBJECT_OPERATOR (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_LOOKING_FOR_PROPERTY (looking-at phps-mode-lexer-LABEL))
-     (lambda()
-       (let ((start (match-beginning 0))
-             (end (match-end 0)))
-         (phps-mode-lexer-yy_pop_state)
-         (phps-mode-lexer-RETURN_TOKEN 'T_STRING start end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_LOOKING_FOR_PROPERTY (looking-at phps-mode-lexer-ANY_CHAR))
-     (lambda()
-       (let ((_start (match-beginning 0))
-             (end (match-end 0)))
-         (phps-mode-lexer-yy_pop_state)
-         ;; TODO goto restart here?
-         ;; (message "Restart here")
-         (phps-mode-lexer-MOVE_FORWARD end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "::"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_PAAMAYIM_NEKUDOTAYIM (match-beginning 
0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\\\"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_NS_SEPARATOR (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\.\\.\\."))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ELLIPSIS (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\?\\?"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_COALESCE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "new"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_NEW (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "clone"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_CLONE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "var"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_VAR (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "\\(int\\|integer\\)" 
phps-mode-lexer-TABS_AND_SPACES ")")))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_INT_CAST (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "\\(real\\|double\\|float\\)" 
phps-mode-lexer-TABS_AND_SPACES ")")))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_DOUBLE_CAST (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "\\(string\\|binary\\)" 
phps-mode-lexer-TABS_AND_SPACES ")")))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_STRING_CAST (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "array" phps-mode-lexer-TABS_AND_SPACES ")")))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ARRAY_CAST (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "object" phps-mode-lexer-TABS_AND_SPACES ")")))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_OBJECT_CAST (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "\\(bool\\|boolean\\)" 
phps-mode-lexer-TABS_AND_SPACES ")")))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_BOOL_CAST (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "unset" phps-mode-lexer-TABS_AND_SPACES ")")))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_UNSET_CAST (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "eval"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_EVAL (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "include"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_INCLUDE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "include_once"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_INCLUDE_ONCE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "require"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_REQUIRE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "require_once"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_REQUIRE_ONCE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "namespace"))
-     (lambda()
-       (setq phps-mode-lexer-declaring_namespace t)
-       (phps-mode-lexer-RETURN_TOKEN 'T_NAMESPACE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "use"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_USE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "insteadof"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_INSTEADOF (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "global"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_GLOBAL (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "isset"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ISSET (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "empty"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_EMPTY (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "__halt_compiler"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_HALT_COMPILER (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "static"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_STATIC (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "abstract"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ABSTRACT (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "final"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_FINAL (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "private"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_PRIVATE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "protected"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_PROTECTED (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "public"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_PUBLIC (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "unset"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_UNSET (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "=>"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_DOUBLE_ARROW (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "list"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_LIST (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "array"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_ARRAY (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "callable"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_CALLABLE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\+\\+"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_INC (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "--"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_DEC (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "==="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_IS_IDENTICAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "!=="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_IS_NOT_IDENTICAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "=="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_IS_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\(!=\\|<>\\)"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_IS_NOT_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "<=>"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_SPACESHIP (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "<="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_IS_SMALLER_OR_EQUAL (match-beginning 
0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at ">="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_IS_GREATER_OR_EQUAL (match-beginning 
0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\+="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_PLUS_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "-="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_MINUS_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\*="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_MUL_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\*\\\\\\*="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_POW_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\*\\\\\\*"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_POW (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "/="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_DIV_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\.="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_CONCAT_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "%="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_MOD_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "<<="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_SL_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at ">>="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_SR_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "&="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_AND_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "|="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_OR_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\^="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_XOR_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\?\\?="))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_COALESCE_EQUAL (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "||"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_BOOLEAN_OR (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "&&"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_BOOLEAN_AND (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "OR"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_LOGICAL_OR (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "AND"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_LOGICAL_AND (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "XOR"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_LOGICAL_XOR (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "<<"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_SL (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at ">>"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_SR (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at phps-mode-lexer-TOKENS))
-     (lambda()
-       (let* ((start (match-beginning 0))
-              (end (match-end 0))
-              (data (buffer-substring-no-properties start end))
-              (use-brace nil))
-         ;; (message "Found token '%s'" data)
-         (when phps-mode-lexer-declaring_namespace
-           (when (string= data ";")
-             (setq phps-mode-lexer-prepend_trailing_brace t)
-             ;; (message "Set flag prepend trailing brace")
-             ;; (setq use-brace t)
+
+  (let ((old-start (point)))
+    (if phps-mode-lexer-tokens
+        (progn
+          ;; Add all updated tokens to semantic
+          (phps-mode-debug-message (message "Updating semantic lexer tokens 
from point %s, tokens: %s, point-max: %s" old-start phps-mode-lexer-tokens 
(point-max)))
+          (dolist (token phps-mode-lexer-tokens)
+            (let ((start (car (cdr token)))
+                  (end (cdr (cdr token)))
+                  (token-name (car token)))
+              (phps-mode-lexer-set-region-syntax-color
+               start end  (phps-mode-lexer-get-token-syntax-color token-name))
+              (semantic-lex-push-token (semantic-lex-token token-name start 
end))))
+
+          (phps-mode-lexer-MOVE_FORWARD (point-max)))
+
+      (phps-mode-debug-message (message "Running lexer from %s" old-start))
+      
+      (let ((heredoc_label (car phps-mode-lexer-heredoc_label_stack))
+            (ST_IN_SCRIPTING (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_IN_SCRIPTING))
+            (ST_INITIAL (= phps-mode-lexer-STATE phps-mode-lexer-ST_INITIAL))
+            (ST_LOOKING_FOR_PROPERTY (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_LOOKING_FOR_PROPERTY))
+            (ST_DOUBLE_QUOTES (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_DOUBLE_QUOTES))
+            (ST_BACKQUOTE (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_BACKQUOTE))
+            (ST_HEREDOC (= phps-mode-lexer-STATE phps-mode-lexer-ST_HEREDOC))
+            (ST_NOWDOC (= phps-mode-lexer-STATE phps-mode-lexer-ST_NOWDOC))
+            (ST_LOOKING_FOR_VARNAME (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_LOOKING_FOR_VARNAME))
+            (ST_END_HEREDOC (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_END_HEREDOC))
+            (ST_VAR_OFFSET (= phps-mode-lexer-STATE 
phps-mode-lexer-ST_VAR_OFFSET)))
+
+        ;; Reset re2c flags
+        (setq phps-mode-lexer-re2c-matching-body nil)
+        (setq phps-mode-lexer-re2c-matching-length nil)
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "exit"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_EXIT (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "die" ))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_DIE (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "function"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_FUNCTION (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "const"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_CONST (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "return"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_RETURN (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at (concat "yield" 
phps-mode-lexer-WHITESPACE "from" "[^a-zA-Z0-9_\x80-\xff]")))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_YIELD_FROM (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "yield"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_YIELD (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "try"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_TRY (match-beginning 0) (match-end 
0))))0
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "catch"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_CATCH (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "finally"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_FINALLY (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "throw"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_THROW (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "if"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_IF (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "elseif"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ELSEIF (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "endif"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ENDIF (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "else"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ELSE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "while"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_WHILE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "endwhile"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ENDWHILE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "do"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_DO (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "for"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_FOR (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "endfor"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ENDFOR (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "foreach"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_FOREACH (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "endforeach"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ENDFOREACH (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "declare"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_DECLARE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "enddeclare"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ENDDECLARE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "instanceof"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_INSTANCEOF (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "as"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_AS (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "switch"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_SWITCH (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "endswitch"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ENDSWITCH (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "case"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_CASE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "default"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_DEFAULT (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "break"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_BREAK (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "continue"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_CONTINUE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "goto"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_GOTO (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "echo"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ECHO (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "print"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_PRINT (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "class"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_CLASS (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "interface"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_INTERFACE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "trait"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_TRAIT (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "extends"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_EXTENDS (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "implements"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_IMPLEMENTS (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "->"))
+         (lambda()
+           (phps-mode-lexer-yy_push_state 
phps-mode-lexer-ST_LOOKING_FOR_PROPERTY)
+           (phps-mode-lexer-RETURN_TOKEN 'T_OBJECT_OPERATOR (match-beginning 
0) (match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and (or ST_IN_SCRIPTING ST_LOOKING_FOR_PROPERTY)
+              (looking-at phps-mode-lexer-WHITESPACE))
+         (lambda()
+           (let* ((start (match-beginning 0))
+                  (end (match-end 0))
+                  (data (buffer-substring-no-properties start end)))
+             (if phps-mode-lexer-PARSER_MODE
+                 (phps-mode-lexer-MOVE_FORWARD end)
+               (phps-mode-lexer-RETURN_TOKEN data start end)))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_LOOKING_FOR_PROPERTY (looking-at "->"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_OBJECT_OPERATOR (match-beginning 
0) (match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_LOOKING_FOR_PROPERTY (looking-at phps-mode-lexer-LABEL))
+         (lambda()
+           (let ((start (match-beginning 0))
+                 (end (match-end 0)))
+             (phps-mode-lexer-yy_pop_state)
+             (phps-mode-lexer-RETURN_TOKEN 'T_STRING start end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_LOOKING_FOR_PROPERTY (looking-at phps-mode-lexer-ANY_CHAR))
+         (lambda()
+           (let ((_start (match-beginning 0))
+                 (end (match-end 0)))
+             (phps-mode-lexer-yy_pop_state)
+             ;; TODO goto restart here?
+             ;; (message "Restart here")
+             (phps-mode-lexer-MOVE_FORWARD end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "::"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_PAAMAYIM_NEKUDOTAYIM 
(match-beginning 0) (match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\\\"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_NS_SEPARATOR (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\.\\.\\."))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ELLIPSIS (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\?\\?"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_COALESCE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "new"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_NEW (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "clone"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_CLONE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "var"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_VAR (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "\\(int\\|integer\\)" 
phps-mode-lexer-TABS_AND_SPACES ")")))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_INT_CAST (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "\\(real\\|double\\|float\\)" 
phps-mode-lexer-TABS_AND_SPACES ")")))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_DOUBLE_CAST (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "\\(string\\|binary\\)" 
phps-mode-lexer-TABS_AND_SPACES ")")))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_STRING_CAST (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "array" phps-mode-lexer-TABS_AND_SPACES ")")))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ARRAY_CAST (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "object" phps-mode-lexer-TABS_AND_SPACES ")")))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_OBJECT_CAST (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "\\(bool\\|boolean\\)" 
phps-mode-lexer-TABS_AND_SPACES ")")))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_BOOL_CAST (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at (concat "(" 
phps-mode-lexer-TABS_AND_SPACES "unset" phps-mode-lexer-TABS_AND_SPACES ")")))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_UNSET_CAST (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "eval"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_EVAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "include"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_INCLUDE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "include_once"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_INCLUDE_ONCE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "require"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_REQUIRE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "require_once"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_REQUIRE_ONCE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "namespace"))
+         (lambda()
+           (setq phps-mode-lexer-declaring_namespace t)
+           (phps-mode-lexer-RETURN_TOKEN 'T_NAMESPACE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "use"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_USE (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "insteadof"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_INSTEADOF (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "global"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_GLOBAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "isset"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ISSET (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "empty"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_EMPTY (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "__halt_compiler"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_HALT_COMPILER (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "static"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_STATIC (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "abstract"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ABSTRACT (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "final"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_FINAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "private"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_PRIVATE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "protected"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_PROTECTED (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "public"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_PUBLIC (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "unset"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_UNSET (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "=>"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_DOUBLE_ARROW (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "list"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_LIST (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "array"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_ARRAY (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "callable"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_CALLABLE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\+\\+"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_INC (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "--"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_DEC (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "==="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_IS_IDENTICAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "!=="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_IS_NOT_IDENTICAL (match-beginning 
0) (match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "=="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_IS_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\(!=\\|<>\\)"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_IS_NOT_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "<=>"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_SPACESHIP (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "<="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_IS_SMALLER_OR_EQUAL 
(match-beginning 0) (match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at ">="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_IS_GREATER_OR_EQUAL 
(match-beginning 0) (match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\+="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_PLUS_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "-="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_MINUS_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\*="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_MUL_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\*\\\\\\*="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_POW_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\*\\\\\\*"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_POW (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "/="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_DIV_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\.="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_CONCAT_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "%="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_MOD_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "<<="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_SL_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at ">>="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_SR_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "&="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_AND_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "|="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_OR_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\^="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_XOR_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\?\\?="))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_COALESCE_EQUAL (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "||"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_BOOLEAN_OR (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "&&"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_BOOLEAN_AND (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "OR"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_LOGICAL_OR (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "AND"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_LOGICAL_AND (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "XOR"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_LOGICAL_XOR (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "<<"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_SL (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at ">>"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_SR (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at phps-mode-lexer-TOKENS))
+         (lambda()
+           (let* ((start (match-beginning 0))
+                  (end (match-end 0))
+                  (data (buffer-substring-no-properties start end))
+                  (use-brace nil))
+             ;; (message "Found token '%s'" data)
+             (when phps-mode-lexer-declaring_namespace
+               (when (string= data ";")
+                 (setq phps-mode-lexer-prepend_trailing_brace t)
+                 ;; (message "Set flag prepend trailing brace")
+                 ;; (setq use-brace t)
+                 )
+               (setq phps-mode-lexer-declaring_namespace nil))
+             (if use-brace
+                 (phps-mode-lexer-RETURN_TOKEN "{" start end)
+               (phps-mode-lexer-RETURN_TOKEN data start end)))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "{"))
+         (lambda()
+           (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_IN_SCRIPTING)
+           (when phps-mode-lexer-declaring_namespace
+             (setq phps-mode-lexer-declaring_namespace nil))
+           (phps-mode-lexer-RETURN_TOKEN "{" (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and (or ST_DOUBLE_QUOTES ST_BACKQUOTE ST_HEREDOC) (looking-at 
"\\${"))
+         (lambda()
+           (phps-mode-lexer-yy_push_state 
phps-mode-lexer-ST_LOOKING_FOR_VARNAME)
+           (phps-mode-lexer-RETURN_TOKEN 'T_DOLLAR_OPEN_CURLY_BRACES 
(match-beginning 0) (match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "}"))
+         (lambda()
+           (when phps-mode-lexer-state_stack
+             ;; (message "State stack %s" phps-mode-lexer-state_stack)
+             ;; (message "popping state from } %s at %s-%s" (length 
phps-mode-lexer-state_stack) (match-beginning 0) (match-end 0))
+             (phps-mode-lexer-yy_pop_state)
+             ;; (message "New state: %s" phps-mode-lexer-STATE)
              )
-           (setq phps-mode-lexer-declaring_namespace nil))
-         (if use-brace
-             (phps-mode-lexer-RETURN_TOKEN "{" start end)
-           (phps-mode-lexer-RETURN_TOKEN data start end)))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "{"))
-     (lambda()
-       (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_IN_SCRIPTING)
-       (when phps-mode-lexer-declaring_namespace
-         (setq phps-mode-lexer-declaring_namespace nil))
-       (phps-mode-lexer-RETURN_TOKEN "{" (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and (or ST_DOUBLE_QUOTES ST_BACKQUOTE ST_HEREDOC) (looking-at "\\${"))
-     (lambda()
-       (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_LOOKING_FOR_VARNAME)
-       (phps-mode-lexer-RETURN_TOKEN 'T_DOLLAR_OPEN_CURLY_BRACES 
(match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "}"))
-     (lambda()
-       (when phps-mode-lexer-state_stack
-         ;; (message "State stack %s" phps-mode-lexer-state_stack)
-         ;; (message "popping state from } %s at %s-%s" (length 
phps-mode-lexer-state_stack) (match-beginning 0) (match-end 0))
-         (phps-mode-lexer-yy_pop_state)
-         ;; (message "New state: %s" phps-mode-lexer-STATE)
-         )
-       (phps-mode-lexer-RETURN_TOKEN "}" (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_LOOKING_FOR_VARNAME (looking-at (concat phps-mode-lexer-LABEL 
"[\\[}]")))
-     (lambda()
-       (let ((start (match-beginning 0))
-             (end (- (match-end 0) 1)))
-         ;; (message "Stopped here")
-         (phps-mode-lexer-yy_pop_state)
-         (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_IN_SCRIPTING)
-         (phps-mode-lexer-RETURN_TOKEN 'T_STRING_VARNAME start end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_LOOKING_FOR_VARNAME (looking-at phps-mode-lexer-ANY_CHAR))
-     (lambda()
-       (phps-mode-lexer-yy_pop_state)
-       (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_IN_SCRIPTING)))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at phps-mode-lexer-BNUM))
-     (lambda()
-       (let* ((start (match-beginning 0))
-              (end (match-end 0))
-              (data (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 start end)
-           (phps-mode-lexer-RETURN_TOKEN 'T_LNUMBER start end)))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at phps-mode-lexer-LNUM))
-     (lambda()
-       (let* ((start (match-beginning 0))
-              (end (match-end 0))
-              (data (string-to-number (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 start end)
-           (phps-mode-lexer-RETURN_TOKEN 'T_LNUMBER start end)))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at phps-mode-lexer-HNUM))
-     (lambda()
-       (let* ((start (match-beginning 0))
-              (end (match-end 0))
-              (data (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 start end)
-           (phps-mode-lexer-RETURN_TOKEN 'T_LNUMBER start end)))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_VAR_OFFSET (looking-at "\\([0]\\|[1-9][0-9]*\\)"))
-     (lambda()
-       (let ((start (match-beginning 0))
-              (end (match-end 0)))
-         (phps-mode-lexer-RETURN_TOKEN 'T_NUM_STRING start end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_VAR_OFFSET (looking-at (concat "\\("
-                                            phps-mode-lexer-LNUM "\\|"
-                                            phps-mode-lexer-HNUM "\\|"
-                                            phps-mode-lexer-BNUM "\\)")))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_NUM_STRING (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (or (looking-at phps-mode-lexer-EXPONENT_DNUM)
-                              (looking-at phps-mode-lexer-DNUM)))
-     (lambda()
-       (let* ((start (match-beginning 0))
-              (end (match-end 0))
-              (_data (buffer-substring-no-properties start end)))
-         ;; (message "Exponent/double at: %s" _data)
-         (phps-mode-lexer-RETURN_TOKEN 'T_DNUMBER start end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "__CLASS__"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_CLASS_C (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "__TRAIT__"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_TRAIT_C (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "__FUNCTION__"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_FUNC_C (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "__METHOD__"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_METHOD_C (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "__LINE__"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_LINE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "__FILE__"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_FILE (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "__DIR__"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_DIR (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "__NAMESPACE__"))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_NS_C (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_INITIAL (looking-at "<\\?="))
-     (lambda()
-       (let ((start (match-beginning 0))
-             (end (match-end 0)))
-         (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
-         ;; (message "Starting scripting after <?=")
-         (when phps-mode-lexer-PARSER_MODE
-           (phps-mode-lexer-RETURN_TOKEN 'T_ECHO start end))
-         (phps-mode-lexer-RETURN_TOKEN 'T_OPEN_TAG_WITH_ECHO start end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_INITIAL (looking-at "<\\?php\\([ \t]\\|\n\\)"))
-     (lambda()
-       (let ((start (match-beginning 0))
-             (end (match-end 0)))
-         (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
-         ;; (message "Starting scripting after <?php")
-         (when phps-mode-lexer-EXPECTED
-           (phps-mode-lexer-SKIP_TOKEN 'T_OPEN_TAG start end))
-         (phps-mode-lexer-RETURN_TOKEN 'T_OPEN_TAG start end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_INITIAL (looking-at "<\\?"))
-     (lambda()
-       (when phps-mode-lexer-SHORT_TAGS
-         (let ((start (match-beginning 0))
-               (end (match-end 0)))
+           (phps-mode-lexer-RETURN_TOKEN "}" (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_LOOKING_FOR_VARNAME (looking-at (concat phps-mode-lexer-LABEL 
"[\\[}]")))
+         (lambda()
+           (let ((start (match-beginning 0))
+                 (end (- (match-end 0) 1)))
+             ;; (message "Stopped here")
+             (phps-mode-lexer-yy_pop_state)
+             (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_IN_SCRIPTING)
+             (phps-mode-lexer-RETURN_TOKEN 'T_STRING_VARNAME start end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_LOOKING_FOR_VARNAME (looking-at phps-mode-lexer-ANY_CHAR))
+         (lambda()
+           (phps-mode-lexer-yy_pop_state)
+           (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_IN_SCRIPTING)))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at phps-mode-lexer-BNUM))
+         (lambda()
+           (let* ((start (match-beginning 0))
+                  (end (match-end 0))
+                  (data (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 start end)
+               (phps-mode-lexer-RETURN_TOKEN 'T_LNUMBER start end)))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at phps-mode-lexer-LNUM))
+         (lambda()
+           (let* ((start (match-beginning 0))
+                  (end (match-end 0))
+                  (data (string-to-number (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 start end)
+               (phps-mode-lexer-RETURN_TOKEN 'T_LNUMBER start end)))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at phps-mode-lexer-HNUM))
+         (lambda()
+           (let* ((start (match-beginning 0))
+                  (end (match-end 0))
+                  (data (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 start end)
+               (phps-mode-lexer-RETURN_TOKEN 'T_LNUMBER start end)))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_VAR_OFFSET (looking-at "\\([0]\\|[1-9][0-9]*\\)"))
+         (lambda()
+           (let ((start (match-beginning 0))
+                 (end (match-end 0)))
+             (phps-mode-lexer-RETURN_TOKEN 'T_NUM_STRING start end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_VAR_OFFSET (looking-at (concat "\\("
+                                                phps-mode-lexer-LNUM "\\|"
+                                                phps-mode-lexer-HNUM "\\|"
+                                                phps-mode-lexer-BNUM "\\)")))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_NUM_STRING (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (or (looking-at phps-mode-lexer-EXPONENT_DNUM)
+                                  (looking-at phps-mode-lexer-DNUM)))
+         (lambda()
+           (let* ((start (match-beginning 0))
+                  (end (match-end 0))
+                  (_data (buffer-substring-no-properties start end)))
+             ;; (message "Exponent/double at: %s" _data)
+             (phps-mode-lexer-RETURN_TOKEN 'T_DNUMBER start end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "__CLASS__"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_CLASS_C (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "__TRAIT__"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_TRAIT_C (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "__FUNCTION__"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_FUNC_C (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "__METHOD__"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_METHOD_C (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "__LINE__"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_LINE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "__FILE__"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_FILE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "__DIR__"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_DIR (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "__NAMESPACE__"))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_NS_C (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_INITIAL (looking-at "<\\?="))
+         (lambda()
+           (let ((start (match-beginning 0))
+                 (end (match-end 0)))
+             (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
+             ;; (message "Starting scripting after <?=")
+             (when phps-mode-lexer-PARSER_MODE
+               (phps-mode-lexer-RETURN_TOKEN 'T_ECHO start end))
+             (phps-mode-lexer-RETURN_TOKEN 'T_OPEN_TAG_WITH_ECHO start end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_INITIAL (looking-at "<\\?php\\([ \t]\\|\n\\)"))
+         (lambda()
+           (let ((start (match-beginning 0))
+                 (end (match-end 0)))
+             (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
+             ;; (message "Starting scripting after <?php")
+             (when phps-mode-lexer-EXPECTED
+               (phps-mode-lexer-SKIP_TOKEN 'T_OPEN_TAG start end))
+             (phps-mode-lexer-RETURN_TOKEN 'T_OPEN_TAG start end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_INITIAL (looking-at "<\\?"))
+         (lambda()
+           (when phps-mode-lexer-SHORT_TAGS
+             (let ((start (match-beginning 0))
+                   (end (match-end 0)))
+               (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
+               (when phps-mode-lexer-EXPECTED
+                 (phps-mode-lexer-SKIP_TOKEN 'T_OPEN_TAG start end))
+               ;; (message "Starting scripting after <?")
+               (phps-mode-lexer-RETURN_TOKEN 'T_OPEN_TAG start end)))))
+
+        ;; NOTE: mimics inline_char_handler
+        (phps-mode-lexer-re2c-rule
+         (and ST_INITIAL (looking-at phps-mode-lexer-ANY_CHAR))
+         (lambda()
+           (let ((start (match-beginning 0)))
+             (let ((string-start (search-forward "<?" nil t)))
+               (if string-start
+                   (phps-mode-lexer-RETURN_TOKEN 'T_INLINE_HTML start (- 
string-start 2))
+                 (phps-mode-lexer-RETURN_TOKEN 'T_INLINE_HTML start 
(point-max)))))))
+
+        (phps-mode-lexer-re2c-rule
+         (and (or ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE) (looking-at 
(concat "\\$" phps-mode-lexer-LABEL "->" "[a-zA-Z_\x80-\xff]")))
+         (lambda()
+           (phps-mode-lexer-yy_push_state 
phps-mode-lexer-ST_LOOKING_FOR_PROPERTY)
+           (forward-char -3)
+           (phps-mode-lexer-RETURN_TOKEN 'T_VARIABLE (match-beginning 0) (- 
(match-end 0) 3))))
+
+        (phps-mode-lexer-re2c-rule
+         (and (or ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE) (looking-at 
(concat "\\$" phps-mode-lexer-LABEL "\\[")))
+         (lambda()
+           (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_VAR_OFFSET)
+           (phps-mode-lexer-RETURN_TOKEN 'T_VARIABLE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and (or ST_IN_SCRIPTING ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE 
ST_VAR_OFFSET) (looking-at (concat "\\$" phps-mode-lexer-LABEL)))
+         (lambda()
+           (phps-mode-lexer-RETURN_TOKEN 'T_VARIABLE (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_VAR_OFFSET (looking-at "\\]"))
+         (lambda()
+           (phps-mode-lexer-yy_pop_state)
+           (phps-mode-lexer-RETURN_TOKEN "]" (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_VAR_OFFSET (looking-at (concat "\\(" phps-mode-lexer-TOKENS
+                                                "\\|[{}\"`]\\)")))
+         (lambda()
+           (let* ((start (match-beginning 0))
+                  (end (match-end 0))
+                  (data (buffer-substring-no-properties start end)))
+             (phps-mode-lexer-RETURN_TOKEN data start end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_VAR_OFFSET (looking-at (concat "[ \n\r\t'#]")))
+         (lambda()
+           (let* ((start (match-beginning 0))
+                  (end (- (match-end 0) 1)))
+             (phps-mode-lexer-yy_pop_state)
+             (phps-mode-lexer-RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE start 
end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and (or ST_IN_SCRIPTING ST_VAR_OFFSET) (looking-at 
phps-mode-lexer-LABEL))
+         (lambda()
+           ;; (message "Adding T_STRING from %s to %s" (match-beginning 0) 
(match-end 0))
+           (phps-mode-lexer-RETURN_TOKEN 'T_STRING (match-beginning 0) 
(match-end 0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\(#\\|//\\)"))
+         (lambda()
+           (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)
+                 (progn
+                   ;; (message "Found comment 1 from %s to %s %s in %s" end (+ 
end (match-beginning 0)) (match-beginning 0) line)
+                   (phps-mode-lexer-RETURN_TOKEN 'T_COMMENT start (+ end 
(match-beginning 0)))
+                   )
+               (progn
+                 ;; TODO Handle expecting values here
+                 ;; (message "Found comment 2 from %s to %s" start 
(line-end-position))
+                 (phps-mode-lexer-RETURN_TOKEN 'T_COMMENT start 
(line-end-position))
+                 )))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at (concat "\\(/\\*\\|/\\*\\*" 
phps-mode-lexer-WHITESPACE "\\)")))
+         (lambda()
+           (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
+                       (phps-mode-lexer-RETURN_TOKEN 'T_DOC_COMMENT start 
(match-end 0))
+                     (phps-mode-lexer-RETURN_TOKEN 'T_COMMENT start (match-end 
0)))
+                 (progn
+                   (display-warning 'phps-mode (format "PHPs Lexer Error - 
Unterminated comment starting at %s" (point)))
+                   (phps-mode-lexer-MOVE_FORWARD (point-max))))))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\\?>\n?"))
+         (lambda()
+           (let ((start (match-beginning 0))
+                 (end (match-end 0)))
+             (when (= (- end start) 3)
+               (setq end (1- end)))
+             (phps-mode-lexer-BEGIN phps-mode-lexer-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-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "'"))
+         (lambda()
+           (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
+                 (progn
+                   ;; (message "Single quoted string %s" 
(buffer-substring-no-properties start un-escaped-end))
+                   (phps-mode-lexer-RETURN_TOKEN 'T_CONSTANT_ENCAPSED_STRING 
start un-escaped-end))
+               (progn
+                 ;; Unclosed single quotes
+                 ;; (message "Single quoted string never ends..")
+                 (phps-mode-lexer-RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE 
start (point-max))
+                 (phps-mode-lexer-MOVE_FORWARD (point-max)))))))
+
+        ;; Double quoted string
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "\""))
+         (lambda()
+           (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
+             (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))
+                           (is-escaped nil))
+
+                       ;; Go to character before match start
+                       (goto-char (1- string-start))
+
+                       ;; Store whether character is escaped or not
+                       (setq is-escaped (looking-at-p "\\\\"))
+
+                       ;; Do we find variable inside quote?
+                       (goto-char string-start)
+
+                       ;; Process character if it's not escaped
+                       (if is-escaped
+                           (forward-char 2)
+                         (setq open-quote nil)
+                         (if (looking-at "\"")
+                             (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 
'T_CONSTANT_ENCAPSED_STRING start (+ string-start 1)))
+                           ;; (message "Found variable after '%s'" 
(buffer-substring-no-properties start string-start))
+                           (phps-mode-lexer-BEGIN 
phps-mode-lexer-ST_DOUBLE_QUOTES)
+                           (phps-mode-lexer-RETURN_TOKEN "\"" start (1+ start))
+                           (phps-mode-lexer-RETURN_TOKEN 
'T_ENCAPSED_AND_WHITESPACE (1+ start) string-start))))
+                   (progn
+                     (display-warning 'phps-mode (format "Found no ending of 
quote at %s" (point)))
+                     (phps-mode-lexer-MOVE_FORWARD (point-max))
+                     (setq open-quote nil))))))))
+
+        (phps-mode-lexer-re2c-rule
+         (and 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)))
+         (lambda()
+           (let* ((start (match-beginning 0))
+                  (end (match-end 0))
+                  (data (buffer-substring-no-properties (match-beginning 1) 
(match-end 1)))
+                  (heredoc_label))
+
+             ;; Determine if it's HEREDOC or NOWDOC and extract label here
+             (if (string= (substring data 0 1) "'")
+                 (progn
+                   (setq heredoc_label (substring data 1 (- (length data) 1)))
+                   (phps-mode-lexer-BEGIN phps-mode-lexer-ST_NOWDOC))
+               (progn
+                 (if (string= (substring data 0 1) "\"")
+                     (setq heredoc_label (substring data 1 (- (length data) 
1)))
+                   (setq heredoc_label data))
+                 (phps-mode-lexer-BEGIN phps-mode-lexer-ST_HEREDOC)))
+
+             ;; Check for ending label on the next line
+             (when (string= (buffer-substring-no-properties end (+ end (length 
heredoc_label))) heredoc_label)
+               (phps-mode-lexer-BEGIN phps-mode-lexer-ST_END_HEREDOC))
+
+             (push heredoc_label phps-mode-lexer-heredoc_label_stack)
+             ;; (message "Found heredoc or nowdoc at %s with label %s" data 
heredoc_label)
+
+             (phps-mode-lexer-RETURN_TOKEN 'T_START_HEREDOC start end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_IN_SCRIPTING (looking-at "[`]"))
+         (lambda()
+           ;; (message "Begun backquote at %s-%s" (match-beginning 0) 
(match-end 0))
+           (phps-mode-lexer-BEGIN phps-mode-lexer-ST_BACKQUOTE)
+           (phps-mode-lexer-RETURN_TOKEN "`" (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_END_HEREDOC (looking-at (concat phps-mode-lexer-ANY_CHAR)))
+         (lambda()
+           (let* ((start (match-beginning 0))
+                  (end (+ start (length heredoc_label) 1))
+                  (_data (buffer-substring-no-properties start end)))
+             ;; (message "Found ending heredoc at %s, %s of %s" _data 
(thing-at-point 'line) heredoc_label)
+             (pop phps-mode-lexer-heredoc_label_stack)
+             (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
+             (phps-mode-lexer-RETURN_TOKEN 'T_END_HEREDOC start end))))
+
+        (phps-mode-lexer-re2c-rule
+         (and (or ST_DOUBLE_QUOTES ST_BACKQUOTE ST_HEREDOC) (looking-at 
(concat "{\\$")))
+         (lambda()
+           (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_IN_SCRIPTING)
+           (phps-mode-lexer-RETURN_TOKEN 'T_CURLY_OPEN (match-beginning 0) (- 
(match-end 0) 1))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_DOUBLE_QUOTES (looking-at "[\"]"))
+         (lambda()
            (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
-           (when phps-mode-lexer-EXPECTED
-             (phps-mode-lexer-SKIP_TOKEN 'T_OPEN_TAG start end))
-           ;; (message "Starting scripting after <?")
-           (phps-mode-lexer-RETURN_TOKEN 'T_OPEN_TAG start end)))))
-
-    ;; NOTE: mimics inline_char_handler
-    (phps-mode-lexer-re2c-rule
-     (and ST_INITIAL (looking-at phps-mode-lexer-ANY_CHAR))
-     (lambda()
-       (let ((start (match-beginning 0)))
-         (let ((string-start (search-forward "<?" nil t)))
-           (if string-start
-               (phps-mode-lexer-RETURN_TOKEN 'T_INLINE_HTML start (- 
string-start 2))
-             (phps-mode-lexer-RETURN_TOKEN 'T_INLINE_HTML start 
(point-max)))))))
-
-    (phps-mode-lexer-re2c-rule
-     (and (or ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE) (looking-at (concat 
"\\$" phps-mode-lexer-LABEL "->" "[a-zA-Z_\x80-\xff]")))
-     (lambda()
-       (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_LOOKING_FOR_PROPERTY)
-       (forward-char -3)
-       (phps-mode-lexer-RETURN_TOKEN 'T_VARIABLE (match-beginning 0) (- 
(match-end 0) 3))))
-
-    (phps-mode-lexer-re2c-rule
-     (and (or ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE) (looking-at (concat 
"\\$" phps-mode-lexer-LABEL "\\[")))
-     (lambda()
-       (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_VAR_OFFSET)
-       (phps-mode-lexer-RETURN_TOKEN 'T_VARIABLE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and (or ST_IN_SCRIPTING ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE 
ST_VAR_OFFSET) (looking-at (concat "\\$" phps-mode-lexer-LABEL)))
-     (lambda()
-       (phps-mode-lexer-RETURN_TOKEN 'T_VARIABLE (match-beginning 0) 
(match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_VAR_OFFSET (looking-at "\\]"))
-     (lambda()
-       (phps-mode-lexer-yy_pop_state)
-       (phps-mode-lexer-RETURN_TOKEN "]" (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_VAR_OFFSET (looking-at (concat "\\(" phps-mode-lexer-TOKENS
-                                            "\\|[{}\"`]\\)")))
-     (lambda()
-       (let* ((start (match-beginning 0))
-              (end (match-end 0))
-              (data (buffer-substring-no-properties start end)))
-         (phps-mode-lexer-RETURN_TOKEN data start end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_VAR_OFFSET (looking-at (concat "[ \n\r\t'#]")))
-     (lambda()
-       (let* ((start (match-beginning 0))
-              (end (- (match-end 0) 1)))
-         (phps-mode-lexer-yy_pop_state)
-         (phps-mode-lexer-RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE start end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and (or ST_IN_SCRIPTING ST_VAR_OFFSET) (looking-at 
phps-mode-lexer-LABEL))
-     (lambda()
-       ;; (message "Adding T_STRING from %s to %s" (match-beginning 0) 
(match-end 0))
-       (phps-mode-lexer-RETURN_TOKEN 'T_STRING (match-beginning 0) (match-end 
0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\(#\\|//\\)"))
-     (lambda()
-       (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)
-             (progn
-               ;; (message "Found comment 1 from %s to %s %s in %s" end (+ end 
(match-beginning 0)) (match-beginning 0) line)
-               (phps-mode-lexer-RETURN_TOKEN 'T_COMMENT start (+ end 
(match-beginning 0)))
-               )
-           (progn
-             ;; TODO Handle expecting values here
-             ;; (message "Found comment 2 from %s to %s" start 
(line-end-position))
-             (phps-mode-lexer-RETURN_TOKEN 'T_COMMENT start 
(line-end-position))
-             )))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at (concat "\\(/\\*\\|/\\*\\*" 
phps-mode-lexer-WHITESPACE "\\)")))
-     (lambda()
-       (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
-                   (phps-mode-lexer-RETURN_TOKEN 'T_DOC_COMMENT start 
(match-end 0))
-                 (phps-mode-lexer-RETURN_TOKEN 'T_COMMENT start (match-end 0)))
-             (progn
-               (display-warning "phps-mode" "PHPs Lexer Error - Unterminated 
comment starting at %s" start)
-               (phps-mode-lexer-RETURN_TOKEN 'T_ERROR start (point-max))
-               (phps-mode-lexer-MOVE_FORWARD (point-max))))))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\\?>\n?"))
-     (lambda()
-       (let ((start (match-beginning 0))
-             (end (match-end 0)))
-         (when (= (- end start) 3)
-           (setq end (1- end)))
-         (phps-mode-lexer-BEGIN phps-mode-lexer-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-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "'"))
-     (lambda()
-       (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
-             (progn
-               ;; (message "Single quoted string %s" 
(buffer-substring-no-properties start un-escaped-end))
-               (phps-mode-lexer-RETURN_TOKEN 'T_CONSTANT_ENCAPSED_STRING start 
un-escaped-end))
-           (progn
-             ;; Unclosed single quotes
-             ;; (message "Single quoted string never ends..")
-             (phps-mode-lexer-RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE start 
(point-max))
-             (phps-mode-lexer-MOVE_FORWARD (point-max)))))))
-
-    ;; Double quoted string
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "\""))
-     (lambda()
-       (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
-         (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?
+           ;; (message "Ended double-quote at %s" (match-beginning 0))
+           (phps-mode-lexer-RETURN_TOKEN "\"" (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_BACKQUOTE (looking-at "[`]"))
+         (lambda()
+           (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
+           (phps-mode-lexer-RETURN_TOKEN "`" (match-beginning 0) (match-end 
0))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_DOUBLE_QUOTES (looking-at phps-mode-lexer-ANY_CHAR))
+         (lambda()
+           (let ((start (point)))
+             (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 
'T_CONSTANT_ENCAPSED_STRING start variable-start)
+                             ))
+                       (progn
+                         (phps-mode-lexer-RETURN_TOKEN 
'T_CONSTANT_ENCAPSED_STRING start end)
+                         ;; (message "Found end of quote at %s-%s, moving 
ahead after '%s'" start end (buffer-substring-no-properties start end))
+                         )))
+                 (progn
+                   (display-warning 'phps-mode (format "Found no ending of 
double quoted region starting at %s" start))
+                   (phps-mode-lexer-MOVE_FORWARD (point-max))))))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_BACKQUOTE (looking-at phps-mode-lexer-ANY_CHAR))
+         (lambda()
+           (let ((string-start (search-forward-regexp 
"\\([^\\\\]`\\|\\$\\|{\\)" nil t)))
              (if string-start
-                 (let ((string-start (match-beginning 0))
-                       (is-escaped nil))
-
-                   ;; Go to character before match start
-                   (goto-char (1- string-start))
-
-                   ;; Store whether character is escaped or not
-                   (setq is-escaped (looking-at-p "\\\\"))
-
-                   ;; Do we find variable inside quote?
-                   (goto-char string-start)
-
-                   ;; Process character if it's not escaped
-                   (if is-escaped
-                       (forward-char 2)
-                     (setq open-quote nil)
-                     (if (looking-at "\"")
-                         (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 
'T_CONSTANT_ENCAPSED_STRING start (+ string-start 1)))
-                       ;; (message "Found variable after '%s'" 
(buffer-substring-no-properties start string-start))
-                       (phps-mode-lexer-BEGIN phps-mode-lexer-ST_DOUBLE_QUOTES)
-                       (phps-mode-lexer-RETURN_TOKEN "\"" start (1+ start))
-                       (phps-mode-lexer-RETURN_TOKEN 
'T_ENCAPSED_AND_WHITESPACE (1+ start) string-start))))
+                 (let ((start (- (match-end 0) 1)))
+                   ;; (message "Skipping backquote forward over %s" 
(buffer-substring-no-properties old-start start))
+                   (phps-mode-lexer-RETURN_TOKEN 'T_CONSTANT_ENCAPSED_STRING 
old-start start)
+                   )
                (progn
-                 ;; (message "Found no ending quote, skipping to end")
-                 (phps-mode-lexer-RETURN_TOKEN 'T_ERROR start (point-max))
-                 (phps-mode-lexer-MOVE_FORWARD (point-max))
-                 (setq open-quote nil))))))))
-
-    (phps-mode-lexer-re2c-rule
-     (and 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)))
-     (lambda()
-       (let* ((start (match-beginning 0))
-              (end (match-end 0))
-              (data (buffer-substring-no-properties (match-beginning 1) 
(match-end 1)))
-              (heredoc_label))
-
-         ;; Determine if it's HEREDOC or NOWDOC and extract label here
-         (if (string= (substring data 0 1) "'")
-             (progn
-               (setq heredoc_label (substring data 1 (- (length data) 1)))
-               (phps-mode-lexer-BEGIN phps-mode-lexer-ST_NOWDOC))
-           (progn
-             (if (string= (substring data 0 1) "\"")
-                 (setq heredoc_label (substring data 1 (- (length data) 1)))
-               (setq heredoc_label data))
-             (phps-mode-lexer-BEGIN phps-mode-lexer-ST_HEREDOC)))
-
-         ;; Check for ending label on the next line
-         (when (string= (buffer-substring-no-properties end (+ end (length 
heredoc_label))) heredoc_label)
-           (phps-mode-lexer-BEGIN phps-mode-lexer-ST_END_HEREDOC))
-
-         (push heredoc_label phps-mode-lexer-heredoc_label_stack)
-         ;; (message "Found heredoc or nowdoc at %s with label %s" data 
heredoc_label)
-
-         (phps-mode-lexer-RETURN_TOKEN 'T_START_HEREDOC start end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_IN_SCRIPTING (looking-at "[`]"))
-     (lambda()
-       ;; (message "Begun backquote at %s-%s" (match-beginning 0) (match-end 
0))
-       (phps-mode-lexer-BEGIN phps-mode-lexer-ST_BACKQUOTE)
-       (phps-mode-lexer-RETURN_TOKEN "`" (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_END_HEREDOC (looking-at (concat phps-mode-lexer-ANY_CHAR)))
-     (lambda()
-       (let* ((start (match-beginning 0))
-              (end (+ start (length heredoc_label) 1))
-              (_data (buffer-substring-no-properties start end)))
-         ;; (message "Found ending heredoc at %s, %s of %s" _data 
(thing-at-point 'line) heredoc_label)
-         (pop phps-mode-lexer-heredoc_label_stack)
-         (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
-         (phps-mode-lexer-RETURN_TOKEN 'T_END_HEREDOC start end))))
-
-    (phps-mode-lexer-re2c-rule
-     (and (or ST_DOUBLE_QUOTES ST_BACKQUOTE ST_HEREDOC) (looking-at (concat 
"{\\$")))
-     (lambda()
-       (phps-mode-lexer-yy_push_state phps-mode-lexer-ST_IN_SCRIPTING)
-       (phps-mode-lexer-RETURN_TOKEN 'T_CURLY_OPEN (match-beginning 0) (- 
(match-end 0) 1))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_DOUBLE_QUOTES (looking-at "[\"]"))
-     (lambda()
-       (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
-       ;; (message "Ended double-quote at %s" (match-beginning 0))
-       (phps-mode-lexer-RETURN_TOKEN "\"" (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_BACKQUOTE (looking-at "[`]"))
-     (lambda()
-       (phps-mode-lexer-BEGIN phps-mode-lexer-ST_IN_SCRIPTING)
-       (phps-mode-lexer-RETURN_TOKEN "`" (match-beginning 0) (match-end 0))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_DOUBLE_QUOTES (looking-at phps-mode-lexer-ANY_CHAR))
-     (lambda()
-       (let ((start (point)))
-         (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 
'T_CONSTANT_ENCAPSED_STRING start variable-start)
-                         ))
-                   (progn
-                     (phps-mode-lexer-RETURN_TOKEN 'T_CONSTANT_ENCAPSED_STRING 
start end)
-                     ;; (message "Found end of quote at %s-%s, moving ahead 
after '%s'" start end (buffer-substring-no-properties start end))
-                     )))
-             (progn
-               ;; "Found no end of double-quoted region
-               (phps-mode-lexer-RETURN_TOKEN 'T_ERROR start (point-max))
-               (phps-mode-lexer-MOVE_FORWARD (point-max))))))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_BACKQUOTE (looking-at phps-mode-lexer-ANY_CHAR))
-     (lambda()
-       (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 old-start start))
-               (phps-mode-lexer-RETURN_TOKEN 'T_CONSTANT_ENCAPSED_STRING 
old-start start)
-               )
-           (progn
-             ;; (message "Found no end of backquote.. skipping to end from %s" 
(buffer-substring-no-properties (point) (point-max)))
-             (phps-mode-lexer-RETURN_TOKEN 'T_ERROR old-start (point-max))
-             (phps-mode-lexer-MOVE_FORWARD (point-max)))))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_HEREDOC (looking-at phps-mode-lexer-ANY_CHAR))
-     (lambda()
-       ;; (message "Found nothing useful at '%s' looking at {$ %s" 
(buffer-substring-no-properties (point) (point-max)) (looking-at "{\\$"))
-       ;; Check for $, ${ and {$ forward
-       (let ((string-start (search-forward-regexp (concat "\\(\n" 
heredoc_label ";?\n\\|\\$" 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 (buffer-substring-no-properties start end)))
-               ;; (message "Found something ending at %s" data)
-
-               (cond
-
-                ((string-match (concat "\n" heredoc_label ";?\n") data)
+                 (display-warning 'phps-mode (format "Found no ending of 
backquoted string starting at %s" (point)))
+                 (phps-mode-lexer-MOVE_FORWARD (point-max)))))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_HEREDOC (looking-at phps-mode-lexer-ANY_CHAR))
+         (lambda()
+           ;; (message "Found nothing useful at '%s' looking at {$ %s" 
(buffer-substring-no-properties (point) (point-max)) (looking-at "{\\$"))
+           ;; Check for $, ${ and {$ forward
+           (let ((string-start (search-forward-regexp (concat "\\(\n" 
heredoc_label ";?\n\\|\\$" 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 (buffer-substring-no-properties start end)))
+                   ;; (message "Found something ending at %s" data)
+
+                   (cond
+
+                    ((string-match (concat "\n" heredoc_label ";?\n") data)
                                         ;, (message "Found heredoc end at 
%s-%s" start end)
-                 (phps-mode-lexer-BEGIN phps-mode-lexer-ST_END_HEREDOC)
-                 (phps-mode-lexer-RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE 
old-start start))
+                     (phps-mode-lexer-BEGIN phps-mode-lexer-ST_END_HEREDOC)
+                     (phps-mode-lexer-RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE 
old-start start))
 
-                (t
-                 ;; (message "Found variable at '%s'.. Skipping forward to %s" 
data start)
-                 (phps-mode-lexer-RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE 
old-start start)
-                 )
+                    (t
+                     ;; (message "Found variable at '%s'.. Skipping forward to 
%s" data start)
+                     (phps-mode-lexer-RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE 
old-start start)
+                     )
+
+                    ))
+               (progn
+                 (display-warning 'phps-mode (format "Found no ending of 
heredoc at %s" (point)))
+                 (phps-mode-lexer-MOVE_FORWARD (point-max)))))))
+
+        (phps-mode-lexer-re2c-rule
+         (and ST_NOWDOC (looking-at phps-mode-lexer-ANY_CHAR))
+         (lambda()
+           (let ((string-start (search-forward-regexp (concat "\n" 
heredoc_label ";?\n") nil t)))
+             (if string-start
+                 (let* ((start (match-beginning 0))
+                        (end (match-end 0))
+                        (_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-BEGIN phps-mode-lexer-ST_END_HEREDOC)
+                   (phps-mode-lexer-RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE 
old-start start)
+                   )
+               (progn
+                 (display-warning 'phps-mode (format "Found no ending of 
newdoc starting at %s" (point)))
+                 (phps-mode-lexer-MOVE_FORWARD (point-max)))))))
 
-                ))
-           (progn
-             ;; (message "Found no ending of heredoc at %s '%s'" heredoc_label 
(buffer-substring-no-properties (point) (point-max)))
-             (phps-mode-lexer-RETURN_TOKEN 'T_ERROR old-start (point-max))
-             (phps-mode-lexer-MOVE_FORWARD (point-max))
-             )))))
-
-    (phps-mode-lexer-re2c-rule
-     (and ST_NOWDOC (looking-at phps-mode-lexer-ANY_CHAR))
-     (lambda()
-       (let ((string-start (search-forward-regexp (concat "\n" heredoc_label 
";?\n") nil t)))
-         (if string-start
-             (let* ((start (match-beginning 0))
-                    (end (match-end 0))
-                    (_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-BEGIN phps-mode-lexer-ST_END_HEREDOC)
-               (phps-mode-lexer-RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE 
old-start start)
-               )
-           (progn
-             ;; (message "Found no ending of nowdoc at %s '%s'" heredoc_label 
(buffer-substring-no-properties (point) (point-max)))
-             (phps-mode-lexer-RETURN_TOKEN 'T_ERROR old-start (point-max))
-             (phps-mode-lexer-MOVE_FORWARD (point-max))
-             )))))
-
-    (phps-mode-lexer-re2c-rule
-     (and (or ST_IN_SCRIPTING ST_VAR_OFFSET) (looking-at 
phps-mode-lexer-ANY_CHAR))
-     (lambda()
-       ;; Unexpected character
-       ;; (message "Unexpected character '%s'" (buffer-substring-no-properties 
(match-beginning 0) (match-end 0)))
-       (phps-mode-lexer-RETURN_TOKEN 'T_ERROR (match-beginning 0) (point-max))
-       (phps-mode-lexer-MOVE_FORWARD (point-max))))
-
-    (phps-mode-lexer-re2c-execute)))
+        (phps-mode-lexer-re2c-rule
+         (and (or ST_IN_SCRIPTING ST_VAR_OFFSET) (looking-at 
phps-mode-lexer-ANY_CHAR))
+         (lambda()
+           (display-warning 'phps-mode (format "Unexpected character at %s" 
(point)))
+           (phps-mode-lexer-MOVE_FORWARD (point-max))))
+
+        (phps-mode-lexer-re2c-execute)))))
 
 (defun phps-mode-lexer-get-tokens ()
   "Get lexer tokens."
@@ -1604,31 +1622,24 @@
 
 (defun phps-mode-lexer-setup (start end)
   "Just prepare other lexers for lexing region START to END."
-  ;; (message "phps-mode-lexer-setup %s %s" start end)
-
-  ;; Flag that buffer has not been processed
-  (when (and (boundp 'phps-mode-functions-processed-buffer)
-             phps-mode-functions-processed-buffer)
-    (setq phps-mode-functions-processed-buffer nil))
-
-  ;; Does lexer start from the beginning of buffer?
-  (when (and (eq start 1)
-             end)
-    (phps-mode-lexer-clear-region-syntax-color (point-min) (point-max))
-
-    (setq phps-mode-lexer-states nil)
-    (phps-mode-lexer-BEGIN phps-mode-lexer-ST_INITIAL)))
+  (phps-mode-debug-message (message "Lexer setup %s - %s" start end))
+  (phps-mode-lexer-BEGIN phps-mode-lexer-ST_INITIAL))
 
 (defun phps-mode-lexer-run ()
   "Run lexer."
   (interactive)
-  ;; (message "Running lexer")
-  (setq phps-mode-lexer-tokens (semantic-lex-buffer)))
+  (phps-mode-debug-message (message "Lexer run"))
+  (setq-local phps-mode-lexer-buffer-length (1- (point-max)))
+  (setq-local phps-mode-lexer-buffer-contents (buffer-substring-no-properties 
(point-min) (point-max)))
+  (setq-local phps-mode-lexer-STATE nil)
+  (setq-local phps-mode-lexer-state_stack nil)
+  (setq-local phps-mode-lexer-states nil)
+  (setq-local phps-mode-lexer-tokens (semantic-lex-buffer)))
 
 (defun phps-mode-lexer-move-states (start diff)
   "Move lexer states after (or equal to) START with modification DIFF."
   (when phps-mode-lexer-states
-    (setq phps-mode-lexer-states (phps-mode-lexer-get-moved-states 
phps-mode-lexer-states start diff))))
+    (setq-local phps-mode-lexer-states (phps-mode-lexer-get-moved-states 
phps-mode-lexer-states start diff))))
 
 (defun phps-mode-lexer-get-moved-states (states start diff)
   "Return moved lexer STATES after (or equal to) START with modification DIFF."
@@ -1656,7 +1667,7 @@
 (defun phps-mode-lexer-move-tokens (start diff)
   "Update tokens with moved lexer tokens after or equal to START with 
modification DIFF."
   (when phps-mode-lexer-tokens
-    (setq phps-mode-lexer-tokens (phps-mode-lexer-get-moved-tokens 
phps-mode-lexer-tokens start diff))))
+    (setq-local phps-mode-lexer-tokens (phps-mode-lexer-get-moved-tokens 
phps-mode-lexer-tokens start diff))))
 
 (defun phps-mode-lexer-get-moved-tokens (old-tokens start diff)
   "Return moved lexer OLD-TOKENS positions after (or equal to) START with DIFF 
points."
@@ -1678,72 +1689,274 @@
               (push token new-tokens))))))
     new-tokens))
 
-;; TODO Consider how imenu-index should be affected by this
-(defun phps-mode-lexer-run-incremental ()
-  "Run incremental lexer based on 
`(phps-mode-functions-get-buffer-changes-start)'."
-  ;; (message "Running incremental lexer")
-  (let ((change-start (phps-mode-functions-get-buffer-changes-start)))
-    (when change-start
-      (when (and (> change-start 1)
-                 phps-mode-lexer-states)
-        (let ((state nil)
-              (state-stack nil)
-              (new-states '())
-              (states (nreverse phps-mode-lexer-states))
-              (previous-token-start nil)
-              (previous-token-end nil)
-              (tokens phps-mode-lexer-tokens))
-
-          ;; Find state and state stack before point of change
-          ;; also determine were previous token to change starts
-          (catch 'stop-iteration
-            (dolist (state-object states)
-              (let ((start (nth 0 state-object))
-                    (end (nth 1 state-object)))
-                (when (< end change-start)
-                  (setq state (nth 2 state-object))
-                  (setq state-stack (nth 3 state-object))
-                  (setq previous-token-start start)
-                  (setq previous-token-end end)
-                  (push state-object new-states))
-                (when (> start change-start)
-                  (throw 'stop-iteration nil)))))
-
-          (if (and state
-                   state-stack)
-              (let ((old-tokens '()))
-
-                ;; Build new list of tokens before point of change
-                (catch 'stop-iteration
-                  (dolist (token tokens)
-                    (let ((_start (car (cdr token)))
-                          (end (cdr (cdr token))))
-                      (if (< end previous-token-end)
-                          (progn
-                            ;; NOTE Does following line make any difference?
-                            ;; (semantic-lex-push-token (semantic-lex-token 
token _start end))
-                            (push token old-tokens))
-                        (throw 'stop-iteration nil)))))
-                (setq old-tokens (nreverse old-tokens))
-
-                ;; Delete all syntax coloring from point of change to end of 
buffer
-                (phps-mode-lexer-clear-region-syntax-color previous-token-end 
(point-max))
-                
-                (let* ((new-tokens (semantic-lex previous-token-start 
(point-max)))
-                       (appended-tokens (append old-tokens new-tokens)))
-                  ;; (message "old-tokens: %s, new-tokens: %s" old-tokens 
new-tokens)
-                  (setq phps-mode-lexer-tokens appended-tokens)
-                  (setq phps-mode-lexer-STATE state)
-                  (setq phps-mode-lexer-state_stack state-stack)
-                  (setq phps-mode-lexer-states new-states)
-                  
-                  ;; (message "Rewinding lex to state: %s and stack: %s and 
states: %s and start: %s old tokens: %s" state state-stack new-states 
previous-token-start old-tokens)
-
-                  ))
-            ;; (display-warning "phps-mode" (format "Found no state to rewind 
to for %s in stack %s, buffer point max: %s" change-start states (point-max)))
-            )))
-      (phps-mode-lexer-run)))
-  (phps-mode-functions-reset-buffer-changes-start))
+(defun phps-mode-lexer-run-incremental (buffer)
+  "Run incremental lexer on BUFFER."
+  (phps-mode-debug-message (message "Run incremental lexer on buffer '%s'" 
buffer))
+  (phps-mode-runtime-debug-message (format "Run incremental lexer on buffer 
'%s'" buffer))
+  (with-current-buffer buffer
+    (let ((changes (phps-mode-functions--get-changes))
+          (run-full-lexer nil)
+          (old-tokens phps-mode-lexer-tokens)
+          (old-states phps-mode-lexer-states)
+          (buffer-length-old phps-mode-lexer-buffer-length)
+          (buffer-contents-old phps-mode-lexer-buffer-contents))
+
+      (if (and changes
+               buffer-length-old
+               buffer-contents-old)
+          (progn
+
+            ;; Reset processed buffer flag
+            (phps-mode-functions-reset-processed-buffer)
+
+            ;; Reset idle timer
+            (phps-mode-functions--cancel-idle-timer)
+
+            ;; Reset buffer changes index
+            (phps-mode-functions--reset-changes)
+
+            ;; Reset tokens and states here
+            (setq-local phps-mode-lexer-tokens nil)
+            (setq-local phps-mode-lexer-states nil)
+            (setq-local phps-mode-lexer-STATE nil)
+            (setq-local phps-mode-lexer-state_stack nil)
+
+            (phps-mode-runtime-debug-message "Processing incremental changes")
+            (phps-mode-debug-message (message "Processing incremental changes: 
%s" changes))
+            (setq run-full-lexer t)
+
+            (dolist (change (nreverse changes))
+              (let ((change-start (nth 0 change))
+                    (change-stop (nth 1 change))
+                    (buffer-length-new (1- (nth 3 change)))
+                    (buffer-contents-new (nth 4 change)))
+                (phps-mode-runtime-debug-message
+                 (format "Running incremental lexer %s - %s" change-start 
change-stop))
+                (phps-mode-debug-message
+                 (message "Running incremental lexer %s - %s" change-start 
change-stop))
+
+                (when (and change-start
+                           change-stop)
+                  (if (and (> change-start 1)
+                           phps-mode-lexer-states
+                           phps-mode-lexer-tokens)
+                      (let ((incremental-state nil)
+                            (incremental-state-stack nil)
+                            (incremental-states nil)
+                            (incremental-tokens nil)
+                            (head-states '())
+                            (tail-states '())
+                            (head-tokens '())
+                            (tail-tokens '())
+                            (buffer-length-delta nil)
+                            (incremental-start 0)
+                            (incremental-stop change-stop)
+                            (change-length (- change-stop change-start))
+                            (appended-tokens nil))
+
+                        (phps-mode-debug-message
+                         (message "Change length: %s" change-length)
+                         (message "Old tokens: %s" old-tokens)
+                         (message "Old states: %s" old-states))
+
+                        ;; (phps-mode-debug-message
+                        ;;  (message "Buffer length old: %s" 
buffer-length-old))
+
+                        ;; 1. Determine incremental start (incremental-start), 
that is at the start of previous token
+                        ;; 2. Build list of tokens before incremental start 
(head-tokens)
+                        ;; 3. Build list of tokens after incremental region 
(tail-tokens)
+                        (dolist (token old-tokens)
+                          (let ((start (car (cdr token)))
+                                (end (cdr (cdr token))))
+                            (cond
+                             ((< end change-start)
+                              (push token head-tokens)
+                              (setq incremental-start start))
+                             ((= end change-start)
+                              (setq incremental-start start))
+                             ((> start change-stop)
+                              (setq incremental-stop end)))))
+                        (setq head-tokens (nreverse head-tokens))
+                        (phps-mode-debug-message
+                         (message "Head tokens: %s" head-tokens)
+                         (message "Incremental start: %s" incremental-start)
+                         (message "Incremental stop: %s" incremental-stop)
+                         (message "Buffer length old: %s" buffer-length-old)
+                         (message "Buffer contents old: %s" 
buffer-contents-old))
+
+                        ;; Calculate change of buffer length
+                        (setq buffer-length-delta (- buffer-length-new 
buffer-length-old))
+
+                        (cond
+                         ((= change-length buffer-length-delta)
+                          (phps-mode-debug-message (message "Flag change as 
insert"))
+                          (setq incremental-stop (+ incremental-stop (1- 
buffer-length-delta))))
+                         ((and (= change-length 0)
+                               (< buffer-length-delta 0))
+                          (phps-mode-debug-message (message "Flag change as 
deletion"))
+                          (setq incremental-stop (+ incremental-stop (abs 
buffer-length-delta))))
+                         (t
+                          (phps-mode-debug-message (message "Do not flag 
change as insert or deletion"))))
+
+                        (dolist (token old-tokens)
+                          (let ((start (car (cdr token))))
+                            (when (>= start incremental-stop)
+                              (push token tail-tokens))))
+                        (setq tail-tokens (nreverse tail-tokens))
+
+                        (phps-mode-debug-message
+                         (message "Incremental start: %s" incremental-start)
+                         (message "Incremental stop: %s" incremental-stop)
+                         (message "Buffer length new: %s" buffer-length-new)
+                         (message "Buffer length old: %s" buffer-length-old)
+                         (message "Buffer length delta: %s" 
buffer-length-delta)
+                         (message "Buffer contents new: %s" 
buffer-contents-new)
+                         (message "Tail tokens: %s" tail-tokens)
+                         (message "From region: %s - %s" incremental-start 
incremental-stop))
+
+                        ;; Did we find a start for the incremental process?
+                        (if (and
+                             (> incremental-start 0)
+                             head-tokens)
+                            (progn
+
+                              (phps-mode-debug-message (message "Found 
positive incremental-start and head tokens"))
+
+                              ;; 1. Determine state (incremental-state) and 
state-stack (incremental-state-stack) at incremental start
+                              ;; 2. Build list of states before incremental 
start (head-states)
+                              ;; 3. Build list of states after incremental 
start (tail-states)
+                              (dolist (state-object (nreverse old-states))
+                                (let ((start (nth 0 state-object))
+                                      (end (nth 1 state-object)))
+                                  (when (< end change-start)
+                                    (setq incremental-state (nth 2 
state-object))
+                                    (setq incremental-state-stack (nth 3 
state-object))
+                                    (push state-object head-states))
+                                  (when (>= start incremental-stop)
+                                    (push state-object tail-states))))
+
+                              (phps-mode-debug-message
+                               (message "Incremental-state: %s" 
incremental-state)
+                               (message "Incremental-state-stack: %s" 
incremental-state-stack)
+                               (message "Head states: %s" head-states)
+                               (message "Tail states: %s" tail-states))
+
+                              ;; Rewind lexer state here
+                              (setq-local phps-mode-lexer-states head-states)
+                              (setq-local phps-mode-lexer-STATE 
incremental-state)
+                              (setq-local phps-mode-lexer-state_stack 
incremental-state-stack)
+
+                              (if head-states
+                                  (progn
+                                    (phps-mode-runtime-debug-message "Found 
head states")
+                                    (phps-mode-debug-message (message "Found 
head states"))
+
+                                    ;; Flag that we should not run ful lexer
+                                    (setq run-full-lexer nil)
+
+                                    ;; Delete all syntax coloring from 
incremental-start to end of incremental-region
+                                    ;; 
(phps-mode-lexer-clear-region-syntax-color incremental-start change-stop)
+
+                                    ;; Do partial lex from previous-token-end 
to change-stop
+                                    (let ((incremental-buffer 
(generate-new-buffer "*PHPs Incremental Buffer*")))
+                                      (save-excursion
+                                        (switch-to-buffer incremental-buffer)
+                                        (delete-region (point-min) (point-max))
+                                        (goto-char (point-max))
+                                        (insert-char 10 (- incremental-start 
2))
+                                        (goto-char (point-max))
+                                        (insert (substring buffer-contents-new 
(- incremental-start 2) incremental-stop))
+
+                                        ;; Rewind lexer state here
+                                        (setq-local phps-mode-lexer-states 
head-states)
+                                        (setq-local phps-mode-lexer-STATE 
incremental-state)
+                                        (setq-local 
phps-mode-lexer-state_stack incremental-state-stack)
+
+                                        ;; Setup lexer
+                                        (setq-local semantic-lex-analyzer 
#'phps-mode-lexer-lex)
+                                        (setq-local semantic-lex-syntax-table 
(phps-mode-get-syntax-table))
+
+                                        (phps-mode-debug-message
+                                         (message "Incremental buffer 
contents: \n%s" (buffer-substring-no-properties (point-min) (point-max)))
+                                         (message "Incremental buffer lexer 
region (%s-%s): \n%s" (1- incremental-start) (1+ incremental-stop) 
(buffer-substring-no-properties (1- incremental-start) (1+ incremental-stop))))
+
+                                        (setq incremental-tokens (semantic-lex 
(1- incremental-start) (1+ incremental-stop)))
+                                        (setq appended-tokens (append 
head-tokens incremental-tokens))
+                                        (setq incremental-states 
phps-mode-lexer-states)
+
+                                        (phps-mode-debug-message (message 
"Incremental tokens: %s" incremental-tokens))
+
+                                        (kill-buffer)))
+
+                                    (if (and (= phps-mode-lexer-STATE 
incremental-state)
+                                             (equal 
phps-mode-lexer-state_stack incremental-state-stack))
+                                        (progn
+
+                                          (phps-mode-runtime-debug-message 
"Found matching state and state-stack, copying old state and tokens")
+                                          (phps-mode-debug-message (message 
"Found matching state and state-stack, copying old state and tokens"))
+
+                                          (unless (= buffer-length-delta 0)
+                                            (when tail-tokens
+                                              (setq tail-tokens 
(phps-mode-lexer-get-moved-tokens tail-tokens 0 buffer-length-delta)))
+
+                                            (when tail-states
+                                              (setq tail-states 
(phps-mode-lexer-get-moved-states tail-states 0 buffer-length-delta))))
+
+                                          (phps-mode-debug-message
+                                           (message "State and state stack at 
stop equals state at stop: %s %s" phps-mode-lexer-STATE 
phps-mode-lexer-state_stack))
+
+                                          ;; TODO re-use rest of indexes here? 
(indentation and imenu)
+
+                                          ;; Apply syntax coloring
+                                          (dolist (token-object 
incremental-tokens)
+                                            (let ((token (car token-object))
+                                                  (start (car (cdr 
token-object)))
+                                                  (end (cdr (cdr 
token-object))))
+                                              (when (<= end (point-max))
+                                                
(phps-mode-lexer-set-region-syntax-color
+                                                 start end 
(phps-mode-lexer-get-token-syntax-color token)))))
+
+                                          (setq-local phps-mode-lexer-states 
(append tail-states incremental-states))
+                                          (phps-mode-debug-message (message 
"New states from incremental lex are: %s" phps-mode-lexer-states))
+                                          
+                                          (setq appended-tokens (append 
appended-tokens tail-tokens))
+                                          (phps-mode-debug-message (message 
"New tokens from incremental lex are: %s" appended-tokens)))
+
+                                      (phps-mode-runtime-debug-message "Did 
not find matching state and state-stack, lexing rest of buffer")
+                                      (phps-mode-debug-message (message "Did 
not find matching state and state-stack, lexing rest of buffer"))
+
+                                      (phps-mode-debug-message
+                                       (message "State at stop %s or state 
stack %s does not equals state at stop: %s %s" phps-mode-lexer-STATE 
phps-mode-lexer-state_stack incremental-state incremental-state-stack))
+
+                                      ;; Clear syntax colouring of rest of 
buffer
+                                      ;; 
(phps-mode-lexer-clear-region-syntax-color incremental-start (point-max))
+
+                                      ;; Lex rest of buffer
+                                      (setq head-tokens appended-tokens)
+                                      (setq incremental-tokens (semantic-lex 
incremental-stop (point-max)))
+                                      (setq appended-tokens (append 
head-tokens incremental-tokens))
+                                      (phps-mode-debug-message (message "New 
states from full lex are: %s" phps-mode-lexer-states))
+                                      (phps-mode-debug-message (message "New 
tokens from full lex are: %s" appended-tokens)))
+
+                                    (phps-mode-runtime-debug-message (format 
"Final tokens: %s" appended-tokens))
+                                    (phps-mode-debug-message (message "Final 
tokens: %s" appended-tokens))
+                                    (setq-local phps-mode-lexer-tokens 
appended-tokens))
+                                (phps-mode-runtime-debug-message "Did not find 
head states")
+                                (phps-mode-debug-message (message "Did not 
find head states"))))
+                          (phps-mode-debug-message (message "Did not find 
positive incremental-start or head-tokens"))))
+                    (phps-mode-debug-message (message "Change start not above 
one or lacking tokens or states"))))
+                (setq buffer-length-old buffer-length-new)
+                (setq buffer-contents-old buffer-contents-new)))
+
+            (setq-local phps-mode-lexer-buffer-length (1- (point-max)))
+            (setq-local phps-mode-lexer-buffer-contents 
(buffer-substring-no-properties (point-min) (point-max))))
+        (phps-mode-runtime-debug-message "Found no changes")
+        (phps-mode-debug-message (message "Found no changes")))
+
+      (when run-full-lexer
+        (phps-mode-runtime-debug-message "Running full lexer")
+        (phps-mode-debug-message (message "Running full lexer"))
+        (phps-mode-lexer-run)))))
 
 (define-lex phps-mode-lexer-lex
   "Call lexer analyzer action."
diff --git a/phps-mode-macros.el b/phps-mode-macros.el
new file mode 100644
index 0000000..8bed5e7
--- /dev/null
+++ b/phps-mode-macros.el
@@ -0,0 +1,19 @@
+;;; phps-mode-macros.el --- Macros for major mode -*- lexical-binding: t -*-
+
+;; Copyright (C) 2018-2019  Free Software Foundation, Inc.
+
+;;; Commentary:
+
+
+;;; Code:
+
+(defconst phps-mode-macrotime-debug nil
+  "Debug messages during macro expansion time, default nil.")
+
+(defmacro phps-mode-debug-message (&rest message)
+  "Display debug MESSAGE when debug flag is on."
+  `(when ,phps-mode-macrotime-debug
+    ,@message))
+
+(provide 'phps-mode-macros)
+;;; phps-mode-macros.el ends here
diff --git a/phps-mode-map.el b/phps-mode-map.el
deleted file mode 100644
index 230e091..0000000
--- a/phps-mode-map.el
+++ /dev/null
@@ -1,38 +0,0 @@
-;; phps-mode-map.el --- Map for PHPs -*- lexical-binding:t -*-
-
-;; Copyright (C) 2017-2019  Free Software Foundation, Inc.
-
-;; This file is not part of GNU Emacs.
-
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2, or (at
-;; your option) any later version.
-
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
-
-
-;;; Commentary:
-
-;; Please see README.md from the same repository for extended documentation.
-
-
-;;; Code:
-
-;; NOTE This variable will be created automatically
-(defvar phps-mode-map nil "Key-map for major mode.")
-
-(defun phps-mode-map-init ()
-  "Apply map to mode."
-  (define-key phps-mode-map (kbd "C-c /") #'comment-region)
-  (define-key phps-mode-map (kbd "C-c DEL") #'uncomment-region)
-  (use-local-map phps-mode-map))
-
-(provide 'phps-mode-map)
-;;; phps-mode-map.el ends here
diff --git a/phps-mode-test-functions.el b/phps-mode-test-functions.el
index d0f8161..af03831 100644
--- a/phps-mode-test-functions.el
+++ b/phps-mode-test-functions.el
@@ -26,6 +26,7 @@
 ;;; Code:
 
 (require 'ert)
+(require 'phps-mode)
 (require 'phps-mode-functions)
 (require 'phps-mode-lexer)
 (require 'phps-mode-test)
@@ -566,6 +567,7 @@
    "<html><head><title><?php if ($myCondition) {\n    if ($mySeconCondition) 
{\n        echo $title2;\n\n    } ?></title><body>Bla bla</body></html>"
    "Mixed HTML/PHP with if expression and token-less lines"
    ;; (message "Tokens: %s" phps-mode-lexer-tokens)
+   ;; (message "Indent: %s" (phps-mode-test-hash-to-list 
(phps-mode-functions-get-lines-indent)))
    (should (equal '((1 (0 0)) (2 (1 0)) (3 (2 0)) (4 (2 0)) (5 (1 0))) 
(phps-mode-test-hash-to-list (phps-mode-functions-get-lines-indent)))))
 
   (phps-mode-test-with-buffer
@@ -848,6 +850,11 @@
   "Test for imenu."
 
   (phps-mode-test-with-buffer
+   "<?php\nfunction myFunctionA() {}\nfunction myFunctionB() {}\n$var = 
function () {\n    echo 'here';\n};"
+   "Imenu function-oriented file with anonymous function"
+   (should (equal (phps-mode-functions-get-imenu) '(("myFunctionA" . 16) 
("myFunctionB" . 42)))))
+
+  (phps-mode-test-with-buffer
    "<?php\nfunction myFunctionA() {}\nfunction myFunctionB() {}\n"
    "Imenu function-oriented file"
    (should (equal (phps-mode-functions-get-imenu) '(("myFunctionA" . 16) 
("myFunctionB" . 42)))))
@@ -858,6 +865,11 @@
    (should (equal (phps-mode-functions-get-imenu) '(("myClass" . 
(("myFunctionA" . 43) ("myFunctionB" . 83)))))))
 
   (phps-mode-test-with-buffer
+   "<?php\ninterface myInterface {\n    public function myFunctionA() {}\n    
protected function myFunctionB() {}\n}\n"
+   "Imenu object-oriented file with interface"
+   (should (equal (phps-mode-functions-get-imenu) '(("myInterface" . 
(("myFunctionA" . 51) ("myFunctionB" . 91)))))))
+
+  (phps-mode-test-with-buffer
    "<?php\nnamespace myNamespace {\n    class myClass {\n        public 
function myFunctionA() {}\n        protected function myFunctionB() {}\n    
}\n}\n"
    "Imenu object-oriented file with namespace, class and function"
    (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass" 
("myFunctionA" . 75) ("myFunctionB" . 119)))))))
@@ -902,7 +914,7 @@
 (defun phps-mode-test-functions-get-moved-imenu ()
   "Test for moving imenu index."
 
-  (message "Moved imenu %s" (phps-mode-functions-get-moved-imenu 
'(("myNamespace" ("myClass" ("myFunctionA" . 108) ("myFunctionB" . 161)))) 0 2))
+  ;; (message "Moved imenu %s" (phps-mode-functions-get-moved-imenu 
'(("myNamespace" ("myClass" ("myFunctionA" . 108) ("myFunctionB" . 161)))) 0 2))
 
   (should (equal
            '(("myNamespace" ("myClass" ("myFunctionA" . 110) ("myFunctionB" . 
163))))
@@ -955,94 +967,6 @@
 
   )
 
-;; TODO Add functionality for (delete-backward-char) as well
-;; TODO Test imenu movement here as well
-(defun phps-mode-test-functions-whitespace-modifications ()
-  "Test white-space modifications functions."
-
-  (phps-mode-test-with-buffer
-   "<?php\n$var = 'abc';\n\n$var2 = '123';\n"
-   "Add newline between two assignments and inspect moved tokens and states"
-   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
-   ;; (message "States: %s" (phps-mode-lexer-get-states))
-
-   ;; Initial state
-   (should (equal (phps-mode-lexer-get-tokens)
-                  '((T_OPEN_TAG 1 . 7) (T_VARIABLE 7 . 11) ("=" 12 . 13) 
(T_CONSTANT_ENCAPSED_STRING 14 . 19) (";" 19 . 20) (T_VARIABLE 22 . 27) ("=" 28 
. 29) (T_CONSTANT_ENCAPSED_STRING 30 . 35) (";" 35 . 36))))
-
-   (should (equal (phps-mode-lexer-get-states)
-                  '((35 36 1 (1 1 1 1 1)) (30 35 1 (1 1 1 1 1)) (28 29 1 (1 1 
1 1 1)) (22 27 1 (1 1 1 1 1)) (19 20 1 (1 1 1 1 1)) (14 19 1 (1 1 1 1 1)) (12 
13 1 (1 1 1 1 1)) (7 11 1 (1 1 1 1 1)) (1 7 1 (1 1 1 1 1)))))
-
-   ;; Insert newline
-   (goto-char 21)
-   (newline nil nil)
-
-   ;; Final state
-   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
-   ;; (message "States: %s" (phps-mode-lexer-get-states))
-   (should (equal (phps-mode-lexer-get-tokens)
-                  '((T_OPEN_TAG 1 . 7) (T_VARIABLE 7 . 11) ("=" 12 . 13) 
(T_CONSTANT_ENCAPSED_STRING 14 . 19) (";" 19 . 20) (T_VARIABLE 23 . 28) ("=" 29 
. 30) (T_CONSTANT_ENCAPSED_STRING 31 . 36) (";" 36 . 37))))
-
-   (should (equal (phps-mode-lexer-get-states)
-               '((36 37 1 (1 1 1 1 1)) (31 36 1 (1 1 1 1 1)) (29 30 1 (1 1 1 1 
1)) (23 28 1 (1 1 1 1 1)) (19 20 1 (1 1 1 1 1)) (14 19 1 (1 1 1 1 1)) (12 13 1 
(1 1 1 1 1)) (7 11 1 (1 1 1 1 1)) (1 7 1 (1 1 1 1 1)))))
-   
-   )
-
-  (phps-mode-test-with-buffer
-   "<?php\nif (true):\n    $var = 'abc';\n    $var2 = '123';\nendif;\n"
-   "Add newline inside if body after two assignments and inspect moved tokens 
and states"
-
-   ;; Initial state
-   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
-   ;; (message "States: %s" (phps-mode-lexer-get-states))
-   (should (equal (phps-mode-lexer-get-tokens)
-                  '((T_OPEN_TAG 1 . 7) (T_IF 7 . 9) ("(" 10 . 11) (T_STRING 11 
. 15) (")" 15 . 16) (":" 16 . 17) (T_VARIABLE 22 . 26) ("=" 27 . 28) 
(T_CONSTANT_ENCAPSED_STRING 29 . 34) (";" 34 . 35) (T_VARIABLE 40 . 45) ("=" 46 
. 47) (T_CONSTANT_ENCAPSED_STRING 48 . 53) (";" 53 . 54) (T_ENDIF 55 . 60) (";" 
60 . 61))))
-
-   (should (equal (phps-mode-lexer-get-states)
-                  '((60 61 1 (1 1 1 1 1)) (55 60 1 (1 1 1 1 1)) (53 54 1 (1 1 
1 1 1)) (48 53 1 (1 1 1 1 1)) (46 47 1 (1 1 1 1 1)) (40 45 1 (1 1 1 1 1)) (34 
35 1 (1 1 1 1 1)) (29 34 1 (1 1 1 1 1)) (27 28 1 (1 1 1 1 1)) (22 26 1 (1 1 1 1 
1)) (16 17 1 (1 1 1 1 1)) (15 16 1 (1 1 1 1 1)) (11 15 1 (1 1 1 1 1)) (10 11 1 
(1 1 1 1 1)) (7 9 1 (1 1 1 1 1)) (1 7 1 (1 1 1 1 1)))))
-
-   ;; Insert newline and then indent
-   (goto-char 54)
-   (newline-and-indent)
-
-   ;; Final state
-   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
-   ;; (message "States: %s" (phps-mode-lexer-get-states))
-   (should (equal (phps-mode-lexer-get-tokens)
-                  '((T_OPEN_TAG 1 . 7) (T_IF 7 . 9) ("(" 10 . 11) (T_STRING 11 
. 15) (")" 15 . 16) (":" 16 . 17) (T_VARIABLE 22 . 26) ("=" 27 . 28) 
(T_CONSTANT_ENCAPSED_STRING 29 . 34) (";" 34 . 35) (T_VARIABLE 40 . 45) ("=" 46 
. 47) (T_CONSTANT_ENCAPSED_STRING 48 . 53) (";" 53 . 54) (T_ENDIF 60 . 65) (";" 
65 . 66))))
-
-   (should (equal (phps-mode-lexer-get-states)
-                  '((65 66 1 (1 1 1 1 1)) (60 65 1 (1 1 1 1 1)) (53 54 1 (1 1 
1 1 1)) (48 53 1 (1 1 1 1 1)) (46 47 1 (1 1 1 1 1)) (40 45 1 (1 1 1 1 1)) (34 
35 1 (1 1 1 1 1)) (29 34 1 (1 1 1 1 1)) (27 28 1 (1 1 1 1 1)) (22 26 1 (1 1 1 1 
1)) (16 17 1 (1 1 1 1 1)) (15 16 1 (1 1 1 1 1)) (11 15 1 (1 1 1 1 1)) (10 11 1 
(1 1 1 1 1)) (7 9 1 (1 1 1 1 1)) (1 7 1 (1 1 1 1 1)))))
-
-   )
-
-  (phps-mode-test-with-buffer
-   "<?php\nif (true):\n    $var = \"abc\nanother line here\nmore text 
here\";\n    $var2 = '123';\nendif;"
-   "Add test for inserting newlines inside token"
-
-   ;; (message "Before Tokens %s" (phps-mode-lexer-get-tokens))
-   ;; (message "Before States: %s" (phps-mode-lexer-get-states))
-
-   (should (equal (phps-mode-lexer-get-tokens)
-                  '((T_OPEN_TAG 1 . 7) (T_IF 7 . 9) ("(" 10 . 11) (T_STRING 11 
. 15) (")" 15 . 16) (":" 16 . 17) (T_VARIABLE 22 . 26) ("=" 27 . 28) 
(T_CONSTANT_ENCAPSED_STRING 29 . 67) (";" 67 . 68) (T_VARIABLE 73 . 78) ("=" 79 
. 80) (T_CONSTANT_ENCAPSED_STRING 81 . 86) (";" 86 . 87) (T_ENDIF 88 . 93) (";" 
93 . 94))))
-   (should (equal (phps-mode-lexer-get-states)
-                  '((93 94 1 (1 1 1 1 1)) (88 93 1 (1 1 1 1 1)) (86 87 1 (1 1 
1 1 1)) (81 86 1 (1 1 1 1 1)) (79 80 1 (1 1 1 1 1)) (73 78 1 (1 1 1 1 1)) (67 
68 1 (1 1 1 1 1)) (29 67 1 (1 1 1 1 1)) (27 28 1 (1 1 1 1 1)) (22 26 1 (1 1 1 1 
1)) (16 17 1 (1 1 1 1 1)) (15 16 1 (1 1 1 1 1)) (11 15 1 (1 1 1 1 1)) (10 11 1 
(1 1 1 1 1)) (7 9 1 (1 1 1 1 1)) (1 7 1 (1 1 1 1 1)))))
-
-   ;; Insert newline and then indent
-   (goto-char 51)
-   (newline-and-indent)
-
-   ;; (message "After Tokens %s" (phps-mode-lexer-get-tokens))
-   ;; (message "After States: %s" (phps-mode-lexer-get-states))
-   (should (equal (phps-mode-lexer-get-tokens)
-                  '((T_OPEN_TAG 1 . 7) (T_IF 7 . 9) ("(" 10 . 11) (T_STRING 11 
. 15) (")" 15 . 16) (":" 16 . 17) (T_VARIABLE 22 . 26) ("=" 27 . 28) 
(T_CONSTANT_ENCAPSED_STRING 29 . 76) (";" 76 . 77) (T_VARIABLE 82 . 87) ("=" 88 
. 89) (T_CONSTANT_ENCAPSED_STRING 90 . 95) (";" 95 . 96) (T_ENDIF 97 . 102) 
(";" 102 . 103))))
-   (should (equal (phps-mode-lexer-get-states)
-                  '((102 103 1 (1 1 1 1 1)) (97 102 1 (1 1 1 1 1)) (95 96 1 (1 
1 1 1 1)) (90 95 1 (1 1 1 1 1)) (88 89 1 (1 1 1 1 1)) (82 87 1 (1 1 1 1 1)) (76 
77 1 (1 1 1 1 1)) (29 76 1 (1 1 1 1 1)) (27 28 1 (1 1 1 1 1)) (22 26 1 (1 1 1 1 
1)) (16 17 1 (1 1 1 1 1)) (15 16 1 (1 1 1 1 1)) (11 15 1 (1 1 1 1 1)) (10 11 1 
(1 1 1 1 1)) (7 9 1 (1 1 1 1 1)) (1 7 1 (1 1 1 1 1)))))
-
-   )
-
-  )
-
 (defun phps-mode-test-functions-get-inline-html-indentation ()
   "Test function."
 
@@ -1084,7 +1008,7 @@
 (defun phps-mode-test-functions ()
   "Run test for functions."
   ;; (setq debug-on-error t)
-  ;; (setq phps-mode-functions-verbose t)
+  (setq phps-mode-runtime-debug t)
   (phps-mode-test-functions-get-inline-html-indentation)
   (phps-mode-test-functions-get-lines-indent-if)
   (phps-mode-test-functions-get-lines-indent-classes)
@@ -1098,8 +1022,7 @@
   (phps-mode-test-functions-imenu)
   (phps-mode-test-functions-get-moved-imenu)
   (phps-mode-test-functions-comment-uncomment-region)
-  (phps-mode-test-functions-move-lines-indent)
-  (phps-mode-test-functions-whitespace-modifications))
+  (phps-mode-test-functions-move-lines-indent))
 
 (phps-mode-test-functions)
 
diff --git a/phps-mode-test-integration.el b/phps-mode-test-integration.el
index 91a1c31..bc572e8 100644
--- a/phps-mode-test-integration.el
+++ b/phps-mode-test-integration.el
@@ -30,6 +30,9 @@
 (require 'phps-mode-lexer)
 (require 'phps-mode-test)
 
+(eval-when-compile
+  (require 'phps-mode-macros))
+
 (defun phps-mode-test-integration-incremental ()
   "Test for object-oriented PHP file."
 
@@ -39,8 +42,7 @@
 
    ;; Make changes - insert a new function
    (goto-char 144)
-   (insert "\n\n        public function myFunctionB()\n        {\n            
echo 'my second statement';\n        }\n")
-   (should (equal (phps-mode-functions-get-buffer-changes-start) 144)))
+   (insert "\n\n        public function myFunctionB()\n        {\n            
echo 'my second statement';\n        }\n"))
 
   (phps-mode-test-incremental-vs-intial-buffer
    "<?php\nnamespace myNamespace\n{\n    class myClass\n    {\n        public 
function myFunction()\n        {\n            echo 'my statement';\n        }\n 
   }\n}\n"
@@ -49,19 +51,12 @@
    ;; Make changes - insert a new function
    (goto-char 144)
    (insert "\n\n        public function myFunctionB()\n        {\n            
echo 'my second statement';\n        }\n")
-   (should (equal (phps-mode-functions-get-buffer-changes-start) 144))
-
-   ;; Run incremental lexer
-   (phps-mode-lexer-run-incremental)
 
    ;; Make changes - remove first function
    (goto-char 55)
    (push-mark nil t t)
    (goto-char 145)
-   (execute-kbd-macro (kbd "<backspace>"))
-
-   ;; Test
-   (should (equal (phps-mode-functions-get-buffer-changes-start) 55)))
+   (execute-kbd-macro (kbd "<backspace>")))
 
   (phps-mode-test-incremental-vs-intial-buffer
    ""
@@ -69,31 +64,211 @@
 
    ;; Make changes
    (goto-char 1)
-   (insert "<?php\nfunction myFunctionA()\n{\n    echo 'my second 
statement';\n}\n")
+   (insert "<?php\nfunction myFunctionA()\n{\n    echo 'my second 
statement';\n}\n"))
+
+  (phps-mode-test-incremental-vs-intial-buffer
+   "<?php\nnamespace myNamespace\n{\n    class myClass\n    {\n        public 
function myFunction()\n        {\n            echo 'my statement';\n        }\n 
   }\n}\n"
+   "Integration-test 4 for regular PHP with namespaces, classes and functions, 
minor insert"
+
+   ;; Make changes
+   (goto-char 132)
+   (insert " is a complex one"))
+
+  
+  (phps-mode-test-incremental-vs-intial-buffer
+   "<?php\nnamespace myNamespace\n{\n    class myClass\n    {\n        public 
function myFunction()\n        {\n            echo 'my statement';\n        }\n 
   }\n}\n"
+   "Integration-test 5 for regular PHP with namespaces, classes and functions, 
single deletion"
 
-   ;; Test
-   (should (equal (phps-mode-functions-get-buffer-changes-start) 1)))
+   ;; Make changes - insert a echo
+   (goto-char 132)
+   (backward-delete-char-untabify 1))
 
   (phps-mode-test-incremental-vs-intial-buffer
-   "<?php\n/**\n *\n */\nnamespace myNamespace\n{\n    class myClass\n    {\n  
      public function myFunction()\n        {\n            echo 'my 
statement';\n        }\n    }\n}\n"
-   "Integration-test 4 for regular PHP with namespaces, classes and functions, 
white-space change inside token"
+   "<?php\nnamespace myNamespace\n{\n    class myClass\n    {\n        public 
function myFunction()\n        {\n        echo 'my statement';\n        }\n    
}\n}\n"
+   "Integration-test 6 for regular PHP with namespaces, classes and functions, 
single indent line"
 
    ;; Make changes
-   (goto-char 13)
+   (goto-char 110)
+   (indent-according-to-mode))
+
+  (phps-mode-test-incremental-vs-intial-buffer
+   "<?php\nnamespace myNamespace\n{\n    class myClass\n    {\n        public 
function myFunction()\n        {\n            echo 'my statement';\n        }\n 
   }\n}\n"
+   "Integration-test 7 for regular PHP with namespaces, classes and functions, 
with multiple, isolated edits"
+
+   ;; Make changes
+   (goto-char 110)
+   (indent-according-to-mode)
+
+   ;; Make changes
+   (goto-char 28)
+   (insert "One"))
+
+  (phps-mode-test-incremental-vs-intial-buffer
+   "<?php\nif ($myCondition) {}\n"
+   "Integration-test 8 for regular PHP with newline between curly brackets"
+
+   ;; Make changes
+   (goto-char 26)
+   (execute-kbd-macro (kbd "RET")))
+
+  (phps-mode-test-incremental-vs-intial-buffer
+   "<?php\n/**\n * @see Something\n * @see here\n *\n */\n"
+   "Integration-test 9 for regular PHP with newline in doc comment block"
+
+   ;; Make changes
+   (goto-char 41)
+   (execute-kbd-macro (kbd "RET")))
+
+  )
+
+;; TODO Add functionality for (delete-backward-char) as well
+(defun phps-mode-test-integration-whitespace-modifications ()
+  "Test white-space modifications functions."
+
+  (phps-mode-test-with-buffer
+   "<?php\n$var = 'abc';\n\n$var2 = '123';\n"
+   "Add newline between two assignments and inspect moved tokens and states"
+   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
+   ;; (message "States: %s" (phps-mode-lexer-get-states))
+
+   ;; Initial state
+
+   ;; Tokens
+   (should (equal (phps-mode-lexer-get-tokens)
+                  '((T_OPEN_TAG 1 . 7) (T_VARIABLE 7 . 11) ("=" 12 . 13) 
(T_CONSTANT_ENCAPSED_STRING 14 . 19) (";" 19 . 20) (T_VARIABLE 22 . 27) ("=" 28 
. 29) (T_CONSTANT_ENCAPSED_STRING 30 . 35) (";" 35 . 36))))
+
+   ;; States
+   (should (equal (phps-mode-lexer-get-states)
+                  '((35 36 1 nil) (30 35 1 nil) (28 29 1 nil) (22 27 1 nil) 
(19 20 1 nil) (14 19 1 nil) (12 13 1 nil) (7 11 1 nil) (1 7 1 nil))))
+   
+   ;; Insert newline
+   (goto-char 21)
+   (newline)
+
+   ;; Final state
+   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
+   ;; (message "States: %s" (phps-mode-lexer-get-states))
+   (phps-mode-lexer-run-incremental (current-buffer))
+   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
+   ;; (message "States: %s" (phps-mode-lexer-get-states))
+
+   ;; Tokens
+   (should (equal (phps-mode-lexer-get-tokens)
+                  '((T_OPEN_TAG 1 . 7) (T_VARIABLE 7 . 11) ("=" 12 . 13) 
(T_CONSTANT_ENCAPSED_STRING 14 . 19) (";" 19 . 20) (T_VARIABLE 23 . 28) ("=" 29 
. 30) (T_CONSTANT_ENCAPSED_STRING 31 . 36) (";" 36 . 37))))
+
+   ;; States
+   (should (equal (phps-mode-lexer-get-states)
+                  '((36 37 1 nil) (31 36 1 nil) (29 30 1 nil) (23 28 1 nil) 
(19 20 1 nil) (14 19 1 nil) (12 13 1 nil) (7 11 1 nil) (1 7 1 nil)))))
+
+  (phps-mode-test-with-buffer
+   "<?php\n$var = 'abc';\n\n$var2 = '123';\n"
+   "Delete backward char between two assignments and inspect moved tokens and 
states"
+   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
+   ;; (message "States: %s" (phps-mode-lexer-get-states))
+
+   ;; Initial state
+
+   ;; Tokens
+   (should (equal (phps-mode-lexer-get-tokens)
+                  '((T_OPEN_TAG 1 . 7) (T_VARIABLE 7 . 11) ("=" 12 . 13) 
(T_CONSTANT_ENCAPSED_STRING 14 . 19) (";" 19 . 20) (T_VARIABLE 22 . 27) ("=" 28 
. 29) (T_CONSTANT_ENCAPSED_STRING 30 . 35) (";" 35 . 36))))
+
+   ;; States
+   (should (equal (phps-mode-lexer-get-states)
+                  '((35 36 1 nil) (30 35 1 nil) (28 29 1 nil) (22 27 1 nil) 
(19 20 1 nil) (14 19 1 nil) (12 13 1 nil) (7 11 1 nil) (1 7 1 nil))))
+
+   ;; Insert newline
+   (goto-char 21)
+   (delete-char 1)
+
+   (phps-mode-lexer-run-incremental (current-buffer))
+
+   ;; Final state
+   ;; (message "Modified buffer: '%s'" (buffer-substring-no-properties 
(point-min) (point-max)))
+   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
+   ;; (message "States: %s" (phps-mode-lexer-get-states))
+
+   ;; Tokens
+   (should (equal (phps-mode-lexer-get-tokens)
+                  '((T_OPEN_TAG 1 . 7) (T_VARIABLE 7 . 11) ("=" 12 . 13) 
(T_CONSTANT_ENCAPSED_STRING 14 . 19) (";" 19 . 20) (T_VARIABLE 21 . 26) ("=" 27 
. 28) (T_CONSTANT_ENCAPSED_STRING 29 . 34) (";" 34 . 35))))
+
+   ;; States
+   (should (equal (phps-mode-lexer-get-states)
+                  '((34 35 1 nil) (29 34 1 nil) (27 28 1 nil) (21 26 1 nil) 
(19 20 1 nil) (14 19 1 nil) (12 13 1 nil) (7 11 1 nil) (1 7 1 nil)))))
+
+  (phps-mode-test-with-buffer
+   "<?php\nif (true):\n    $var = 'abc';\n    $var2 = '123';\nendif;\n"
+   "Add newline inside if body after two assignments and inspect moved tokens 
and states"
+
+   ;; Initial state
+   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
+   ;; (message "States: %s" (phps-mode-lexer-get-states))
+   (should (equal (phps-mode-lexer-get-tokens)
+                  '((T_OPEN_TAG 1 . 7) (T_IF 7 . 9) ("(" 10 . 11) (T_STRING 11 
. 15) (")" 15 . 16) (":" 16 . 17) (T_VARIABLE 22 . 26) ("=" 27 . 28) 
(T_CONSTANT_ENCAPSED_STRING 29 . 34) (";" 34 . 35) (T_VARIABLE 40 . 45) ("=" 46 
. 47) (T_CONSTANT_ENCAPSED_STRING 48 . 53) (";" 53 . 54) (T_ENDIF 55 . 60) (";" 
60 . 61))))
+
+   (should (equal (phps-mode-lexer-get-states)
+                  '((60 61 1 nil) (55 60 1 nil) (53 54 1 nil) (48 53 1 nil) 
(46 47 1 nil) (40 45 1 nil) (34 35 1 nil) (29 34 1 nil) (27 28 1 nil) (22 26 1 
nil) (16 17 1 nil) (15 16 1 nil) (11 15 1 nil) (10 11 1 nil) (7 9 1 nil) (1 7 1 
nil))))
+
+   ;; Insert newline and then indent
+   (goto-char 54)
    (newline-and-indent)
 
-   (should (equal (phps-mode-functions-get-buffer-changes-start) nil)))
+   (phps-mode-lexer-run-incremental (current-buffer))
+
+   ;; Final state
+   ;; (message "Tokens %s" (phps-mode-lexer-get-tokens))
+   ;; (message "States: %s" (phps-mode-lexer-get-states))
+   (should (equal (phps-mode-lexer-get-tokens)
+                  '((T_OPEN_TAG 1 . 7) (T_IF 7 . 9) ("(" 10 . 11) (T_STRING 11 
. 15) (")" 15 . 16) (":" 16 . 17) (T_VARIABLE 22 . 26) ("=" 27 . 28) 
(T_CONSTANT_ENCAPSED_STRING 29 . 34) (";" 34 . 35) (T_VARIABLE 40 . 45) ("=" 46 
. 47) (T_CONSTANT_ENCAPSED_STRING 48 . 53) (";" 53 . 54) (T_ENDIF 60 . 65) (";" 
65 . 66))))
+
+   (should (equal (phps-mode-lexer-get-states)
+                  '((65 66 1 nil) (60 65 1 nil) (53 54 1 nil) (48 53 1 nil) 
(46 47 1 nil) (40 45 1 nil) (34 35 1 nil) (29 34 1 nil) (27 28 1 nil) (22 26 1 
nil) (16 17 1 nil) (15 16 1 nil) (11 15 1 nil) (10 11 1 nil) (7 9 1 nil) (1 7 1 
nil)))))
+
+  (phps-mode-test-with-buffer
+   "<?php\nif (true):\n    $var = \"abc\nanother line here\nmore text 
here\";\n    $var2 = '123';\nendif;"
+   "Add test for inserting newlines inside token"
+
+   ;; (message "Before Tokens %s" (phps-mode-lexer-get-tokens))
+   ;; (message "Before States: %s" (phps-mode-lexer-get-states))
+
+   (should (equal (phps-mode-lexer-get-tokens)
+                  '((T_OPEN_TAG 1 . 7) (T_IF 7 . 9) ("(" 10 . 11) (T_STRING 11 
. 15) (")" 15 . 16) (":" 16 . 17) (T_VARIABLE 22 . 26) ("=" 27 . 28) 
(T_CONSTANT_ENCAPSED_STRING 29 . 67) (";" 67 . 68) (T_VARIABLE 73 . 78) ("=" 79 
. 80) (T_CONSTANT_ENCAPSED_STRING 81 . 86) (";" 86 . 87) (T_ENDIF 88 . 93) (";" 
93 . 94))))
+   (should (equal (phps-mode-lexer-get-states)
+                  '((93 94 1 nil) (88 93 1 nil) (86 87 1 nil) (81 86 1 nil) 
(79 80 1 nil) (73 78 1 nil) (67 68 1 nil) (29 67 1 nil) (27 28 1 nil) (22 26 1 
nil) (16 17 1 nil) (15 16 1 nil) (11 15 1 nil) (10 11 1 nil) (7 9 1 nil) (1 7 1 
nil))))
+
+   ;; Insert newline and then indent
+   (goto-char 51)
+   (newline-and-indent)
+
+   (phps-mode-lexer-run-incremental (current-buffer))
+
+   ;; (message "After Tokens %s" (phps-mode-lexer-get-tokens))
+   ;; (message "After States: %s" (phps-mode-lexer-get-states))
+   (should (equal (phps-mode-lexer-get-tokens)
+                  '((T_OPEN_TAG 1 . 7) (T_IF 7 . 9) ("(" 10 . 11) (T_STRING 11 
. 15) (")" 15 . 16) (":" 16 . 17) (T_VARIABLE 22 . 26) ("=" 27 . 28) 
(T_CONSTANT_ENCAPSED_STRING 29 . 76) (";" 76 . 77) (T_VARIABLE 82 . 87) ("=" 88 
. 89) (T_CONSTANT_ENCAPSED_STRING 90 . 95) (";" 95 . 96) (T_ENDIF 97 . 102) 
(";" 102 . 103))))
+   (should (equal (phps-mode-lexer-get-states)
+                  '((102 103 1 nil) (97 102 1 nil) (95 96 1 nil) (90 95 1 nil) 
(88 89 1 nil) (82 87 1 nil) (76 77 1 nil) (29 76 1 nil) (27 28 1 nil) (22 26 1 
nil) (16 17 1 nil) (15 16 1 nil) (11 15 1 nil) (10 11 1 nil) (7 9 1 nil) (1 7 1 
nil)))))
+
+  (phps-mode-test-with-buffer
+   "<?php\nfunction myFunctionA() {}\nfunction myFunctionB() {}\n"
+   "White-space changes in imenu function-oriented file"
+
+   (should (equal (phps-mode-functions-get-imenu) '(("myFunctionA" . 16) 
("myFunctionB" . 42))))
+
+   (goto-char 32)
+   (newline-and-indent)
+
+   (phps-mode-lexer-run-incremental (current-buffer))
+
+   (should (equal (phps-mode-functions-get-imenu) '(("myFunctionA" . 16) 
("myFunctionB" . 43)))))
 
   )
 
 (defun phps-mode-test-integration ()
   "Run test for integration."
-  ;; (setq debug-on-error t)
-  ;; (setq phps-mode-functions-verbose t)
-
+  (setq debug-on-error t)
+  (setq phps-mode-runtime-debug t)
   (phps-mode-test-integration-incremental)
-
-)
+  (phps-mode-test-integration-whitespace-modifications))
 
 (phps-mode-test-integration)
 
diff --git a/phps-mode-test-lexer.el b/phps-mode-test-lexer.el
index c4ed6af..0b3b05b 100644
--- a/phps-mode-test-lexer.el
+++ b/phps-mode-test-lexer.el
@@ -26,6 +26,7 @@
 ;;; Code:
 
 (require 'ert)
+(require 'phps-mode)
 (require 'phps-mode-lexer)
 (require 'phps-mode-test)
 
@@ -311,13 +312,13 @@
 
   (phps-mode-test-with-buffer
    "<?php\nnamespace MyNameSpace{\n\tclass MyClass {\n\t\tpublic function 
__construct() {\n\t\t\texit;\n\t\t}\n\t}\n}\n"
-   nil
+   "Object-oriented namespace file"
    (should (equal (phps-mode-lexer-get-tokens)
                   '((T_OPEN_TAG 1 . 7) (T_NAMESPACE 7 . 16) (T_STRING 17 . 28) 
("{" 28 . 29) (T_CLASS 31 . 36) (T_STRING 37 . 44) ("{" 45 . 46) (T_PUBLIC 49 . 
55) (T_FUNCTION 56 . 64) (T_STRING 65 . 76) ("(" 76 . 77) (")" 77 . 78) ("{" 79 
. 80) (T_EXIT 84 . 88) (";" 88 . 89) ("}" 92 . 93) ("}" 95 . 96) ("}" 97 . 
98)))))
 
   (phps-mode-test-with-buffer
    "<?php\nNAMESPACE MyNameSpace;\nCLASS MyClass {\n\tpublic function 
__construct() {\n\t\texit;\n\t}\n}\n"
-   nil
+   "Capitalized object-oriented namespace file"
    (should (equal (phps-mode-lexer-get-tokens)
                   '((T_OPEN_TAG 1 . 7) (T_NAMESPACE 7 . 16) (T_STRING 17 . 28) 
(";" 28 . 29) (T_CLASS 30 . 35) (T_STRING 36 . 43) ("{" 44 . 45) (T_PUBLIC 47 . 
53) (T_FUNCTION 54 . 62) (T_STRING 63 . 74) ("(" 74 . 75) (")" 75 . 76) ("{" 77 
. 78) (T_EXIT 81 . 85) (";" 85 . 86) ("}" 88 . 89) ("}" 90 . 91)))))
   )
@@ -327,21 +328,21 @@
 
   (phps-mode-test-with-buffer
    "<?php\necho \"My neverending double quotation\n"
-   nil
+   "Neverending double quotation"
    (should (equal (phps-mode-lexer-get-tokens)
-                  '((T_OPEN_TAG 1 . 7) (T_ECHO 7 . 11) (T_ERROR 12 . 45)))))
+                  '((T_OPEN_TAG 1 . 7) (T_ECHO 7 . 11)))))
 
   (phps-mode-test-with-buffer
    "<?php\n`My neverending backquotes\n"
-   nil
+   "Neverending backquotes"
    (should (equal (phps-mode-lexer-get-tokens)
-                  '((T_OPEN_TAG 1 . 7) ("`" 7 . 8) (T_ERROR 8 . 34)))))
+                  '((T_OPEN_TAG 1 . 7) ("`" 7 . 8)))))
 
   (phps-mode-test-with-buffer
    "<?php\n<<<LABEL\nMy neverending heredoc\ngoes on forever\n"
-   nil
+   "Neverending heredoc"
    (should (equal (phps-mode-lexer-get-tokens)
-                  '((T_OPEN_TAG 1 . 7) (T_START_HEREDOC 7 . 16) (T_ERROR 16 . 
55)))))
+                  '((T_OPEN_TAG 1 . 7) (T_START_HEREDOC 7 . 16)))))
 
   )
 
@@ -426,7 +427,6 @@
   "Run test for lexer."
   ;; (message "-- Running all tests for lexer... --\n")
   ;; (setq debug-on-error t)
-  ;; (setq phps-mode-functions-verbose t)
   (phps-mode-test-lexer-script-boundaries)
   (phps-mode-test-lexer-simple-tokens)
   (phps-mode-test-lexer-complex-tokens)
diff --git a/phps-mode-test-syntax-table.el b/phps-mode-test-syntax-table.el
index b512fc7..84305bd 100644
--- a/phps-mode-test-syntax-table.el
+++ b/phps-mode-test-syntax-table.el
@@ -29,7 +29,7 @@
 (require 'phps-mode-functions)
 (require 'phps-mode-test)
 
-;; TODO Should test `forward-sexp', `forward-word', `forward-list' as well
+;; TODO Should test `backward-sexp', `forward-sexp', `backward-word', 
`forward-word', `backward-list', `forward-list' as well
 
 (defun phps-mode-test-syntax-table-quote-region ()
   "Test double quotes, single quotes, curly bracket, square bracket, round 
bracket, back-quotes on regions."
@@ -93,7 +93,6 @@
    (execute-kbd-macro (kbd "`"))
    (let ((buffer-contents (buffer-substring-no-properties (point-min) 
(point-max))))
      (should (equal buffer-contents "<?php\n$var = `abc`;"))))
-  
 
   )
 
diff --git a/phps-mode-test.el b/phps-mode-test.el
index e9098f4..8050594 100644
--- a/phps-mode-test.el
+++ b/phps-mode-test.el
@@ -47,47 +47,45 @@
      (switch-to-buffer test-buffer-incremental)
      (insert ,source)
      (goto-char 0)
-     (when (and (boundp 'phps-mode-functions-verbose)
-                phps-mode-functions-verbose)
+     (phps-mode-debug-message
        (message "\nTesting incremental buffer '%s':\n'%s'\n" ,title ,source))
      (phps-mode)
      ,@change
-     (phps-mode-lexer-run-incremental)
-     (setq incremental-states (phps-mode-lexer-get-states))
-     (setq incremental-tokens (phps-mode-lexer-get-tokens))
-     (setq incremental-imenu (phps-mode-functions-get-imenu))
-     (setq incremental-indent (phps-mode-test-hash-to-list 
(phps-mode-functions-get-lines-indent)))
-     (setq incremental-buffer (buffer-substring-no-properties (point-min) 
(point-max)))
+     (phps-mode-lexer-run-incremental test-buffer-incremental)
+     (phps-mode-functions-process-current-buffer)
+     (setq incremental-states phps-mode-lexer-states)
+     (setq incremental-tokens phps-mode-lexer-tokens)
+     (setq incremental-imenu phps-mode-functions-imenu)
+     (setq incremental-indent (phps-mode-test-hash-to-list 
phps-mode-functions-lines-indent))
+     (setq incremental-buffer (buffer-substring (point-min) (point-max)))
 
      ;; Setup incremental buffer
      (switch-to-buffer test-buffer-initial)
      (insert incremental-buffer)
      (goto-char 0)
-     (when (and (boundp 'phps-mode-functions-verbose)
-                phps-mode-functions-verbose)
+     (phps-mode-debug-message
        (message "\nTesting initial buffer '%s':\n'%s'\n" ,title 
incremental-buffer))
      (phps-mode)
-     (setq initial-states (phps-mode-lexer-get-states))
-     (setq initial-tokens (phps-mode-lexer-get-tokens))
-     (setq initial-imenu (phps-mode-functions-get-imenu))
-     (setq initial-indent (phps-mode-test-hash-to-list 
(phps-mode-functions-get-lines-indent)))
-     (setq initial-buffer (buffer-substring-no-properties (point-min) 
(point-max)))
+     (phps-mode-functions-process-current-buffer)
+     (setq initial-states phps-mode-lexer-states)
+     (setq initial-tokens phps-mode-lexer-tokens)
+     (setq initial-imenu phps-mode-functions-imenu)
+     (setq initial-indent (phps-mode-test-hash-to-list 
phps-mode-functions-lines-indent))
+     (setq initial-buffer (buffer-substring (point-min) (point-max)))
 
      ;; Run tests
-     (when (and (boundp 'phps-mode-functions-verbose)
-                phps-mode-functions-verbose)
+     (phps-mode-debug-message
        (message "\nComparing tokens, lines indent and imenu  between 
buffer:\n\n'%s'\n\nand:\n\n'%s'\n" initial-buffer incremental-buffer))
      (should (equal initial-buffer incremental-buffer))
      ;; (message "Initial tokens: %s\n" initial-tokens)
      ;; (message "Incremental tokens: %s\n" incremental-tokens)
-     (should (equal initial-states incremental-states))
      (should (equal initial-tokens incremental-tokens))
+     (should (equal initial-states incremental-states))
      ;; (message "Initial indent: %s\n" initial-indent)
      ;; (message "Incremental indent: %s\n" incremental-indent)
      (should (equal initial-indent incremental-indent))
      (should (equal initial-imenu incremental-imenu))
 
-
      (kill-buffer test-buffer-incremental)
      (kill-buffer test-buffer-initial)
 
@@ -100,8 +98,7 @@
      (switch-to-buffer test-buffer)
      (insert ,source)
      (goto-char 0)
-     (when (and (boundp 'phps-mode-functions-verbose)
-                phps-mode-functions-verbose)
+     (phps-mode-debug-message
        (message "\nTesting buffer '%s':\n'%s'\n" ,title ,source))
      (phps-mode)
      ,@body
@@ -112,11 +109,14 @@
 (defun phps-mode-test-hash-to-list (hash-table)
   "Return a list that represent the HASH-TABLE.  Each element is a list: (list 
key value)."
   (let (result)
-    (maphash
-     (lambda (k v)
-       (push (list k v) result))
-     hash-table)
-    (sort (nreverse result) (lambda (a b) (< (car a) (car b))))))
+    (if (hash-table-p hash-table)
+        (progn
+          (maphash
+           (lambda (k v)
+             (push (list k v) result))
+           hash-table)
+          (sort (nreverse result) (lambda (a b) (< (car a) (car b)))))
+      nil)))
 
 (provide 'phps-mode-test)
 
diff --git a/phps-mode.el b/phps-mode.el
index d035a18..67a3faf 100644
--- a/phps-mode.el
+++ b/phps-mode.el
@@ -5,8 +5,8 @@
 ;; Author: Christian Johansson <address@hidden>
 ;; Maintainer: Christian Johansson <address@hidden>
 ;; Created: 3 Mar 2018
-;; Modified: 26 Aug 2019
-;; Version: 0.2.8
+;; Modified: 16 Sep 2019
+;; Version: 0.3.1
 ;; Keywords: tools, convenience
 ;; URL: https://github.com/cjohansson/emacs-phps-mode
 
@@ -57,20 +57,61 @@
 (defvar phps-mode-use-psr-2 t
   "Whether to use PSR-2 guidelines for white-space or not.")
 
-(defvar phps-mode-idle-interval 1.0
+(defvar phps-mode-idle-interval 1
   "Idle seconds before running the incremental lexer.")
 
-(defvar phps-mode-flycheck-applied nil "Boolean flag whether flycheck 
configuration has been applied or not.")
+(defvar phps-mode-flycheck-applied nil
+  "Boolean flag whether flycheck configuration has been applied or not.")
 
-(defvar phps-mode-inline-mmm-submode nil "Symbol declaring what mmm-mode to 
use as submode in inline areas.")
+(defvar phps-mode-inline-mmm-submode nil
+  "Symbol declaring what mmm-mode to use as submode in inline areas.")
+
+(defvar phps-mode-runtime-debug nil
+  "Whether or not to use runtime debugging.")
+
+(defun phps-mode-runtime-debug-message (message)
+  "Output MESSAGE if flag is on."
+  (when phps-mode-runtime-debug
+    (let ((buffer (get-buffer-create "*PHPs Debug Messages*")))
+      (with-current-buffer buffer
+        (save-excursion
+          (goto-char (point-max))
+          (insert message)
+          (insert "\n"))))))
+
+(defun phps-mode-get-syntax-table ()
+  "Get syntax table."
+  phps-mode-syntax-table)
 
 (defvar phps-mode-map
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "C-c /") #'comment-region)
     (define-key map (kbd "C-c DEL") #'uncomment-region)
+    (define-key map (kbd "C-c C-r") #'phps-mode-lexer-run)
+    (define-key map (kbd "C-c C-f") #'phps-mode-format-buffer)
+    (define-key map (kbd "C-c C-p") 
#'phps-mode-functions-process-current-buffer)
     map)
   "Keymap for `phps-mode'.")
 
+;;;###autoload
+(defun phps-mode-format-buffer ()
+  "Format current buffer according to PHPs mode."
+  (interactive)
+  (let ((old-buffer-contents (buffer-substring-no-properties (point-min) 
(point-max)))
+        (old-buffer (current-buffer))
+        (temp-buffer (generate-new-buffer "*PHPs Formatting*"))
+        (new-buffer-contents ""))
+    (save-excursion
+      (switch-to-buffer temp-buffer)
+      (insert old-buffer-contents)
+      (phps-mode)
+      (indent-region (point-min) (point-max))
+      (setq new-buffer-contents (buffer-substring-no-properties (point-min) 
(point-max)))
+      (kill-buffer)
+      (switch-to-buffer old-buffer)
+      (delete-region (point-min) (point-max))
+      (insert new-buffer-contents))))
+
 (define-derived-mode phps-mode prog-mode "PHPs"
   "Major mode for PHP with Semantic integration."
 
@@ -87,7 +128,7 @@
     ;; NOTE: These are required for wrapping region functionality
     (transient-mark-mode))
 
-  ;; TODO Add this as a menu setting similar to php-mode
+  ;; TODO Add this as a menu setting similar to php-mode?
   (when phps-mode-use-electric-pair-mode
     (electric-pair-local-mode))
 
@@ -109,7 +150,7 @@
     (flycheck-add-mode 'php-phpcs 'phps-mode)
     (setq phps-mode-flycheck-applied t))
 
-    ;; Custom indentation
+  ;; Custom indentation
   ;; Indent-region will call this on each line of selected region
   (setq-local indent-line-function #'phps-mode-functions-indent-line)
 
@@ -125,15 +166,19 @@
     ;; MUST NOT use tabs for indenting
     (setq-local indent-tabs-mode nil))
 
-  ;; Add support for moving indexes quickly when making newlines
-  (advice-add #'newline :around #'phps-mode-functions-around-newline)
-
   ;; Reset flags
   (setq-local phps-mode-functions-allow-after-change t)
-  (setq-local phps-mode-functions-buffer-changes-start nil)
+  (setq-local phps-mode-functions-buffer-changes nil)
+  (setq-local phps-mode-functions-buffer-changes nil)
+  (setq-local phps-mode-functions-idle-timer nil)
   (setq-local phps-mode-functions-lines-indent nil)
   (setq-local phps-mode-functions-imenu nil)
   (setq-local phps-mode-functions-processed-buffer nil)
+  (setq-local phps-mode-lexer-buffer-length nil)
+  (setq-local phps-mode-lexer-buffer-contents nil)
+  (setq-local phps-mode-lexer-tokens nil)
+  (setq-local phps-mode-lexer-states nil)
+  (setq-local phps-mode-functions-allow-after-change t)
 
   ;; Make (comment-region) and (uncomment-region) work
   (setq-local comment-region-function #'phps-mode-functions-comment-region)
@@ -153,20 +198,19 @@
   ;; Set semantic-lex initializer function
   (add-hook 'semantic-lex-reset-functions #'phps-mode-lexer-setup 0 t)
 
-  ;; Reset tokens
-  (setq-local phps-mode-lexer-tokens nil)
-
   ;; Initial run of lexer
   (phps-mode-lexer-run)
 
   ;; Run semantic functions for new buffer
   (semantic-new-buffer-fcn)
 
+  ;; Disable idle scheduler since we have customized this feature
+  (when (boundp 'semantic-idle-scheduler-mode)
+    (setq semantic-idle-scheduler-mode nil))
+
   ;; Wisent LALR parser TODO
   ;; (phps-mode-tags-init)
-
-  ;; Add compatibility for plug-ins here
-  (run-hooks 'phps-mode-hook))
+  )
 
 (provide 'phps-mode)
 ;;; phps-mode.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]