branch: externals/phps-mode commit df9305fbbbe24e8ca5d773335133b18aebdbfbf8 Author: Christian Johansson <christ...@cvj.se> Commit: Christian Johansson <christ...@cvj.se>
Improved incremental lexer of heredoc and nowdoc --- phps-mode-lex-analyzer.el | 146 +++++++++++++++++++++++-------------- phps-mode-lexer.el | 73 ++++++++++++++----- phps-mode.el | 4 +- test/phps-mode-test-integration.el | 14 +++- test/phps-mode-test-lexer.el | 59 ++++++++++----- 5 files changed, 200 insertions(+), 96 deletions(-) diff --git a/phps-mode-lex-analyzer.el b/phps-mode-lex-analyzer.el index d3a87b3..231a167 100644 --- a/phps-mode-lex-analyzer.el +++ b/phps-mode-lex-analyzer.el @@ -74,12 +74,18 @@ (defvar-local phps-mode-lex-analyzer--state nil "Latest state.") -(defvar-local phps-mode-lex-analyzer--states nil - "History of state and stack-stack.") - (defvar-local phps-mode-lex-analyzer--state-stack nil "Latest state-stack.") +(defvar-local phps-mode-lex-analyzer--states nil + "History of state, heredoc-label, stack-stack and heredoc label stack.") + +(defvar-local phps-mode-lex-analyzer--heredoc-label nil + "Latest Heredoc label.") + +(defvar-local phps-mode-lex-analyzer--heredoc-label-stack nil + "Latest Heredoc label-stack.") + ;; FUNCTIONS @@ -91,6 +97,7 @@ (setq phps-mode-lex-analyzer--idle-timer nil) (setq phps-mode-lex-analyzer--lines-indent nil) (setq phps-mode-lex-analyzer--imenu nil) + (setq phps-mode-lex-analyzer--heredoc-label-stack nil) (setq phps-mode-lex-analyzer--processed-buffer-p nil) (setq phps-mode-lex-analyzer--tokens nil) (setq phps-mode-lex-analyzer--state nil) @@ -355,6 +362,9 @@ (setq phps-mode-lex-analyzer--states (nth 1 result)) (setq phps-mode-lex-analyzer--state (nth 2 result)) (setq phps-mode-lex-analyzer--state-stack (nth 3 result)) + (setq phps-mode-lex-analyzer--heredoc-label (nth 4 result)) + (setq phps-mode-lex-analyzer--heredoc-label-stack (nth 5 result)) + (phps-mode-lex-analyzer--reset-imenu) ;; Apply syntax color on tokens @@ -397,7 +407,7 @@ (defun phps-mode-lex-analyzer--incremental-lex-string (buffer-name buffer-contents incremental-start-new-buffer point-max - head-states incremental-state incremental-state-stack head-tokens &optional force-synchronous) + head-states incremental-state incremental-state-stack incremental-heredoc-label incremental-heredoc-label-stack head-tokens &optional force-synchronous) "Incremental lex region." (let ((async (and (boundp 'phps-mode-async-process) phps-mode-async-process)) @@ -414,6 +424,8 @@ head-states incremental-state incremental-state-stack + incremental-heredoc-label + incremental-heredoc-label-stack head-tokens)) (lambda(result) @@ -427,6 +439,9 @@ (setq phps-mode-lex-analyzer--states (nth 1 result)) (setq phps-mode-lex-analyzer--state (nth 2 result)) (setq phps-mode-lex-analyzer--state-stack (nth 3 result)) + (setq phps-mode-lex-analyzer--heredoc-label (nth 4 result)) + (setq phps-mode-lex-analyzer--heredoc-label-stack (nth 5 result)) + (setq phps-mode-lex-analyzer--processed-buffer-p nil) (phps-mode-lex-analyzer--reset-imenu) @@ -557,6 +572,8 @@ (message "Processing change point minimum: %s" phps-mode-lex-analyzer--change-min)) (let ((incremental-state nil) (incremental-state-stack nil) + (incremental-heredoc-label nil) + (incremental-heredoc-label-stack nil) (incremental-tokens nil) (head-states '()) (head-tokens '()) @@ -574,6 +591,8 @@ (setq phps-mode-lex-analyzer--states nil) (setq phps-mode-lex-analyzer--state nil) (setq phps-mode-lex-analyzer--state-stack nil) + (setq phps-mode-lex-analyzer--heredoc-label nil) + (setq phps-mode-lex-analyzer--heredoc-label-stack nil) ;; NOTE Starts are inclusive while ends are exclusive buffer locations @@ -605,8 +624,10 @@ (phps-mode-debug-message (message "Found head tokens")) + ;; TODO Change on ST_END_HEREDOC should start before it + ;; In old buffer: - ;; 1. Determine state (incremental-state) and state-stack (incremental-state-stack) before incremental start + ;; 1. Determine state (incremental-state) and state-stack (incremental-state-stack) heredoc label (incremental-heredoc-label) heredoc-label-stack (heredoc-label-stack) before incremental start ;; 2. Build list of states before incremental start (head-states) (catch 'quit (dolist (state-object (nreverse old-states)) @@ -615,13 +636,17 @@ (progn (setq incremental-state (nth 2 state-object)) (setq incremental-state-stack (nth 3 state-object)) + (setq incremental-heredoc-label (nth 4 state-object)) + (setq incremental-heredoc-label-stack (nth 5 state-object)) (push state-object head-states)) (throw 'quit "break"))))) (phps-mode-debug-message (message "Head states: %s" head-states) (message "Incremental state: %s" incremental-state) - (message "State stack: %s" incremental-state-stack)) + (message "State stack: %s" incremental-state-stack) + (message "Incremental heredoc-label: %s" incremental-heredoc-label) + (message "Incremental heredoc-label-stack: %s" incremental-heredoc-label-stack)) (if (and head-states @@ -644,6 +669,8 @@ head-states incremental-state incremental-state-stack + incremental-heredoc-label + incremental-heredoc-label-stack head-tokens force-synchronous) @@ -2390,60 +2417,67 @@ SQUARE-BRACKET-LEVEL and ROUND-BRACKET-LEVEL." (unless phps-mode-lex-analyzer--state (setq phps-mode-lex-analyzer--state 'ST_INITIAL))) -(defun phps-mode-lex-analyzer--lex-string (contents &optional start end states state state-stack tokens) +(defun phps-mode-lex-analyzer--lex-string (contents &optional start end states state state-stack heredoc-label heredoc-label-stack tokens) "Run lexer on CONTENTS." ;; Create a separate buffer, run lexer inside of it, catch errors and return them ;; to enable nice presentation (require 'phps-mode-macros) - (let ((errors)) - (let ((buffer (generate-new-buffer "*PHPs Lexer*"))) - - ;; Create temporary buffer and run lexer in it - (with-current-buffer buffer - (insert contents) - - (if tokens - (setq phps-mode-lexer--tokens (nreverse tokens)) - (setq phps-mode-lexer--tokens nil)) - (if state - (setq phps-mode-lexer--state state) - (setq phps-mode-lexer--state 'ST_INITIAL)) - (if states - (setq phps-mode-lexer--states states) - (setq phps-mode-lexer--states nil)) - (if state-stack - (setq phps-mode-lexer--state-stack state-stack) - (setq phps-mode-lexer--state-stack nil)) - - ;; Setup lexer settings - (when (boundp 'phps-mode-syntax-table) - (setq semantic-lex-syntax-table phps-mode-syntax-table)) - (setq semantic-lex-analyzer #'phps-mode-lex-analyzer--re2c-lex) - - ;; Catch errors to kill generated buffer - (let ((got-error t)) - (unwind-protect - ;; Run lexer or incremental lexer - (progn - (if (and start end) - (let ((incremental-tokens (semantic-lex start end))) - (setq - phps-mode-lex-analyzer--tokens - (append tokens incremental-tokens))) - (setq - phps-mode-lex-analyzer--tokens - (semantic-lex-buffer))) - (setq got-error nil)) - (when got-error - (kill-buffer)))) - - ;; Copy variables outside of buffer - (setq state phps-mode-lexer--state) - (setq state-stack phps-mode-lexer--state-stack) - (setq states phps-mode-lexer--states) - (setq tokens (nreverse phps-mode-lexer--tokens)) - (kill-buffer))) - (list tokens states state state-stack errors))) + (let ((buffer (generate-new-buffer "*PHPs Lexer*"))) + + ;; Create temporary buffer and run lexer in it + (with-current-buffer buffer + (insert contents) + + (if tokens + (setq phps-mode-lexer--tokens (nreverse tokens)) + (setq phps-mode-lexer--tokens nil)) + (if state + (setq phps-mode-lexer--state state) + (setq phps-mode-lexer--state 'ST_INITIAL)) + (if states + (setq phps-mode-lexer--states states) + (setq phps-mode-lexer--states nil)) + (if state-stack + (setq phps-mode-lexer--state-stack state-stack) + (setq phps-mode-lexer--state-stack nil)) + (if heredoc-label + (setq phps-mode-lexer--heredoc-label heredoc-label) + (setq phps-mode-lexer--heredoc-label nil)) + (if heredoc-label-stack + (setq phps-mode-lexer--heredoc-label-stack heredoc-label-stack) + (setq phps-mode-lexer--heredoc-label-stack nil)) + + ;; Setup lexer settings + (when (boundp 'phps-mode-syntax-table) + (setq semantic-lex-syntax-table phps-mode-syntax-table)) + (setq semantic-lex-analyzer #'phps-mode-lex-analyzer--re2c-lex) + + ;; Catch errors to kill generated buffer + (let ((got-error t)) + (unwind-protect + ;; Run lexer or incremental lexer + (progn + (if (and start end) + (let ((incremental-tokens (semantic-lex start end))) + (setq + phps-mode-lex-analyzer--tokens + (append tokens incremental-tokens))) + (setq + phps-mode-lex-analyzer--tokens + (semantic-lex-buffer))) + (setq got-error nil)) + (when got-error + (kill-buffer)))) + + ;; Copy variables outside of buffer + (setq state phps-mode-lexer--state) + (setq state-stack phps-mode-lexer--state-stack) + (setq states phps-mode-lexer--states) + (setq tokens (nreverse phps-mode-lexer--tokens)) + (setq heredoc-label phps-mode-lexer--heredoc-label) + (setq heredoc-label-stack phps-mode-lexer--heredoc-label-stack) + (kill-buffer))) + (list tokens states state state-stack heredoc-label heredoc-label-stack)) (provide 'phps-mode-lex-analyzer) diff --git a/phps-mode-lexer.el b/phps-mode-lexer.el index d3dbeb6..24d9bbc 100644 --- a/phps-mode-lexer.el +++ b/phps-mode-lexer.el @@ -117,6 +117,9 @@ (defvar-local phps-mode-lexer--states nil "History of state and state-stack.") +(defvar-local phps-mode-lexer--heredoc-label nil + "Current heredoc label.") + (defvar-local phps-mode-lexer--heredoc-label-stack nil "Stack of heredoc labels.") @@ -186,7 +189,13 @@ ;; Push token start, end, lexer state and state stack to variable (push - (list start end phps-mode-lexer--state phps-mode-lexer--state-stack) + (list + start + end + phps-mode-lexer--state + phps-mode-lexer--state-stack + phps-mode-lexer--heredoc-label + phps-mode-lexer--heredoc-label-stack) phps-mode-lexer--states)) (defun phps-mode-lexer--get-next-unescaped (character) @@ -272,8 +281,7 @@ (phps-mode-debug-message (message "Running lexer from %s" old-start)) (phps-mode-lexer--reset-match-data) - (let ((heredoc-label (car phps-mode-lexer--heredoc-label-stack)) - (SHEBANG (equal phps-mode-lexer--state 'SHEBANG)) + (let ((SHEBANG (equal phps-mode-lexer--state 'SHEBANG)) (ST_IN_SCRIPTING (equal phps-mode-lexer--state 'ST_IN_SCRIPTING)) (ST_INITIAL (equal phps-mode-lexer--state 'ST_INITIAL)) (ST_LOOKING_FOR_PROPERTY (equal phps-mode-lexer--state 'ST_LOOKING_FOR_PROPERTY)) @@ -1230,20 +1238,34 @@ ;; 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))) + (setq + phps-mode-lexer--heredoc-label + (substring data 1 (- (length data) 1))) (phps-mode-lexer--BEGIN 'ST_NOWDOC)) (progn (if (string= (substring data 0 1) "\"") - (setq heredoc-label (substring data 1 (- (length data) 1))) - (setq heredoc-label data)) + (setq + phps-mode-lexer--heredoc-label + (substring data 1 (- (length data) 1))) + (setq + phps-mode-lexer--heredoc-label + data)) (phps-mode-lexer--BEGIN 'ST_HEREDOC))) ;; Check for ending label on the next line - (when (string= (buffer-substring-no-properties end (+ end (length heredoc-label))) heredoc-label) + (when (string= + (buffer-substring-no-properties + end + (+ end + (length + phps-mode-lexer--heredoc-label))) + phps-mode-lexer--heredoc-label) (phps-mode-lexer--BEGIN 'ST_END_HEREDOC)) - (push heredoc-label phps-mode-lexer--heredoc-label-stack) - ;; (message "Found heredoc or nowdoc at %s with label %s" data heredoc-label) + (push + phps-mode-lexer--heredoc-label + phps-mode-lexer--heredoc-label-stack) + ;; (message "Found heredoc or nowdoc at %s with label %s" data phps-mode-lexer--heredoc-label) (phps-mode-lexer--RETURN_TOKEN 'T_START_HEREDOC start end))) @@ -1256,9 +1278,12 @@ (phps-mode-lexer--match-macro (and ST_END_HEREDOC (looking-at (concat phps-mode-lexer--ANY_CHAR))) (let* ((start (match-beginning 0)) - (end (+ start (length heredoc-label) 1)) + (end (+ start + (length + phps-mode-lexer--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) + ;; (message "Found ending heredoc at %s, %s of %s" _data (thing-at-point 'line) phps-mode-lexer--heredoc-label) (pop phps-mode-lexer--heredoc-label-stack) (phps-mode-lexer--BEGIN 'ST_IN_SCRIPTING) (phps-mode-lexer--RETURN_TOKEN 'T_END_HEREDOC start end))) @@ -1330,7 +1355,7 @@ (search-forward-regexp (concat "\\(\n" - heredoc-label + phps-mode-lexer--heredoc-label ";?\n\\|\\$" phps-mode-lexer--LABEL "\\|{\\$" @@ -1343,14 +1368,19 @@ (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 something ending at %s" data) (cond - ((string-match (concat "\n" heredoc-label ";?\n") data) + ((string-match + (concat + "\n" + phps-mode-lexer--heredoc-label + ";?\n" + ) data) ;; (message "Found heredoc end at %s-%s" start end) - (phps-mode-lexer--BEGIN 'ST_END_HEREDOC) - (phps-mode-lexer--RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE old-start start)) + (phps-mode-lexer--RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE old-start start) + (phps-mode-lexer--BEGIN 'ST_END_HEREDOC)) (t ;; (message "Found variable at '%s'.. Skipping forward to %s" data start) @@ -1368,15 +1398,20 @@ (phps-mode-lexer--match-macro (and ST_NOWDOC (looking-at phps-mode-lexer--ANY_CHAR)) (let ((start (car (cdr (car phps-mode-lexer--tokens))))) - (let ((string-start (search-forward-regexp (concat "\n" heredoc-label ";?\\\n") nil t))) + (let ((string-start (search-forward-regexp + (concat + "\n" + phps-mode-lexer--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 'ST_END_HEREDOC) - (phps-mode-lexer--RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE old-start start)) + (phps-mode-lexer--RETURN_TOKEN 'T_ENCAPSED_AND_WHITESPACE old-start start) + (phps-mode-lexer--BEGIN 'ST_END_HEREDOC)) (progn (signal 'phps-lexer-error diff --git a/phps-mode.el b/phps-mode.el index b248544..7af158c 100644 --- a/phps-mode.el +++ b/phps-mode.el @@ -5,8 +5,8 @@ ;; Author: Christian Johansson <christ...@cvj.se> ;; Maintainer: Christian Johansson <christ...@cvj.se> ;; Created: 3 Mar 2018 -;; Modified: 18 May 2020 -;; Version: 0.3.49 +;; Modified: 19 May 2020 +;; Version: 0.3.50 ;; Keywords: tools, convenience ;; URL: https://github.com/cjohansson/emacs-phps-mode diff --git a/test/phps-mode-test-integration.el b/test/phps-mode-test-integration.el index 3fefba0..04b8601 100644 --- a/test/phps-mode-test-integration.el +++ b/test/phps-mode-test-integration.el @@ -126,7 +126,6 @@ (insert "\necho 'my comments';\n")) - ;; TODO T_ENCAPSED_AND_WHITESPACE 72 should be removed by deletion (that is implicitly triggered by electric-pair-mode) (phps-mode-test--incremental-vs-intial-buffer "" "Integration-test 11 insert code in empty buffer using macro, use several passes" @@ -150,9 +149,20 @@ (execute-kbd-macro (kbd "TAB")) (execute-kbd-macro (kbd "RET"))) + (phps-mode-test--incremental-vs-intial-buffer + "<?php\n$str = <<<EOD\nExample of string\nspanning multiple lines\nusing heredoc syntax.\nEOD;\n\n/* More complex example, with variables. */\nclass foo\n{\n var $foo;\n var $bar;\n\n function __construct()\n {\n $this->foo = 'Foo';\n $this->bar = array('Bar1', 'Bar2', 'Bar3');\n }\n}\n\n$foo = new foo();\n$name = 'MyName';\n\necho <<<EOT\nMy name is \"$name\". I am printing some $foo->foo.\nNow, I am printing some {$foo->bar[1]}.\nThis should print a capi [...] + "Integration-test 12 complex HEREDOC adding new line with variable in it" + (goto-char 63) + (insert "inserting $variable ")) + + (phps-mode-test--incremental-vs-intial-buffer + "<?php\n$str = <<<EOD\nExample of string\nspanning multiple lines\nusing heredoc syntax.\nEOD;\n\n/* More complex example, with variables. */\nclass foo\n{\n var $foo;\n var $bar;\n\n function __construct()\n {\n $this->foo = 'Foo';\n $this->bar = array('Bar1', 'Bar2', 'Bar3');\n }\n}\n\n$foo = new foo();\n$name = 'MyName';\n\necho <<<EOT\nMy name is \"$name\". I am printing some $foo->foo.\nNow, I am printing some {$foo->bar[1]}.\nThis should print a capi [...] + "Integration-test 13 complex HEREDOC with removed heredoc delimiter" + (goto-char 85) + (kill-line)) + ) -;; TODO Add tests for (delete-backward-char) as well (defun phps-mode-test-integration--whitespace-modifications () "Test white-space modifications functions." diff --git a/test/phps-mode-test-lexer.el b/test/phps-mode-test-lexer.el index 430b867..07ab84f 100644 --- a/test/phps-mode-test-lexer.el +++ b/test/phps-mode-test-lexer.el @@ -229,37 +229,62 @@ '((T_OPEN_TAG 1 . 7) (T_ECHO 7 . 11) ("\"" 12 . 13) (T_ENCAPSED_AND_WHITESPACE 13 . 20) (T_VARIABLE 20 . 30) (T_NUM_STRING 30 . 31) ("]" 31 . 32) (T_CONSTANT_ENCAPSED_STRING 32 . 46) ("\"" 46 . 47) (";" 47 . 48))))) ;; HEREDOC + (phps-mode-test--with-buffer - "<?php echo <<<\"MYLABEL\"\nline 1\n line 2\nMYLABEL\n;" - nil + "<?php\nclass foo {\n public $bar = <<<EOT\nbar\n EOT;\n}\n// Identifier must not be indented\n?>\n" + "Example #1 Invalid example (HEREDOC)" (should (equal phps-mode-lex-analyzer--tokens - '((T_OPEN_TAG 1 . 7) (T_ECHO 7 . 11) (T_START_HEREDOC 12 . 25) (T_ENCAPSED_AND_WHITESPACE 25 . 39) (T_END_HEREDOC 39 . 47) (";" 48 . 49))))) + nil))) (phps-mode-test--with-buffer - "<?php echo <<<MYLABEL\nline 1\n line 2\nMYLABEL\n;" - nil + "<?php\nclass foo {\n public $bar = <<<EOT\nbar\nEOT;\n}\n?>\n" + "Example #2 Valid example (HEREDOC)" (should (equal phps-mode-lex-analyzer--tokens - '((T_OPEN_TAG 1 . 7) (T_ECHO 7 . 11) (T_START_HEREDOC 12 . 23) (T_ENCAPSED_AND_WHITESPACE 23 . 37) (T_END_HEREDOC 37 . 45) (";" 46 . 47))))) + '((T_OPEN_TAG 1 . 7) (T_CLASS 7 . 12) (T_STRING 13 . 16) ("{" 17 . 18) (T_PUBLIC 23 . 29) (T_VARIABLE 30 . 34) ("=" 35 . 36) (T_START_HEREDOC 37 . 44) (T_ENCAPSED_AND_WHITESPACE 44 . 47) (T_END_HEREDOC 47 . 51) (";" 51 . 52) ("}" 53 . 54) (";" 55 . 57) (T_CLOSE_TAG 55 . 57) (T_INLINE_HTML 57 . 58))))) (phps-mode-test--with-buffer - "<?php echo <<<\"MYLABEL\"\nMYLABEL\n" - nil + "<?php\n$str = <<<EOD\nExample of string\nspanning multiple lines\nusing heredoc syntax.\nEOD;\n\n/* More complex example, with variables. */\nclass foo\n{\n var $foo;\n var $bar;\n\n function __construct()\n {\n $this->foo = 'Foo';\n $this->bar = array('Bar1', 'Bar2', 'Bar3');\n }\n}\n\n$foo = new foo();\n$name = 'MyName';\n\necho <<<EOT\nMy name is \"$name\". I am printing some $foo->foo.\nNow, I am printing some {$foo->bar[1]}.\nThis should print a capi [...] + "Example #3 Heredoc string quoting example" (should (equal phps-mode-lex-analyzer--tokens - '((T_OPEN_TAG 1 . 7) (T_ECHO 7 . 11) (T_START_HEREDOC 12 . 25) (T_END_HEREDOC 25 . 33))))) + '((T_OPEN_TAG 1 . 7) (T_VARIABLE 7 . 11) ("=" 12 . 13) (T_START_HEREDOC 14 . 21) (T_ENCAPSED_AND_WHITESPACE 21 . 84) (T_END_HEREDOC 84 . 88) (";" 88 . 89) (T_COMMENT 91 . 134) (T_CLASS 135 . 140) (T_STRING 141 . 144) ("{" 145 . 146) (T_VAR 151 . 154) (T_VARIABLE 155 . 159) (";" 159 . 160) (T_VAR 165 . 168) (T_VARIABLE 169 . 173) (";" 173 . 174) (T_FUNCTION 180 . 188) (T_STRING 189 . 200) ("(" 200 . 201) (")" 201 . 202) ("{" 207 . 208) (T_VARIABLE 217 . 222) (T_OBJECT_OP [...] - ;; Test heredoc with variables $, {$, ${ here (phps-mode-test--with-buffer - "<?php echo <<<\"MYLABEL\"\nline 1 $variable1\n line 2\n${variable2} line 3\n line {$variable3} here\nline 5 $variable[3] here\nMYLABEL;\n" - nil + "<?php\nvar_dump(array(<<<EOD\nfoobar!\nEOD\n));\n?>\n" + "Example #4 Heredoc in arguments example" (should (equal phps-mode-lex-analyzer--tokens - '((T_OPEN_TAG 1 . 7) (T_ECHO 7 . 11) (T_START_HEREDOC 12 . 25) (T_ENCAPSED_AND_WHITESPACE 25 . 32) (T_VARIABLE 32 . 42) (T_ENCAPSED_AND_WHITESPACE 42 . 51) (T_DOLLAR_OPEN_CURLY_BRACES 51 . 53) (T_STRING_VARNAME 53 . 62) ("}" 62 . 63) (T_ENCAPSED_AND_WHITESPACE 63 . 77) (T_CURLY_OPEN 77 . 78) (T_VARIABLE 78 . 88) ("}" 88 . 89) (T_ENCAPSED_AND_WHITESPACE 89 . 102) (T_VARIABLE 102 . 112) (T_NUM_STRING 112 . 113) ("]" 113 . 114) (T_ENCAPSED_AND_WHITESPACE 114 . 119) (T_END_ [...] + '((T_OPEN_TAG 1 . 7) (T_STRING 7 . 15) ("(" 15 . 16) (T_ARRAY 16 . 21) ("(" 21 . 22) (T_START_HEREDOC 22 . 29) (T_ENCAPSED_AND_WHITESPACE 29 . 36) (T_END_HEREDOC 36 . 40) (")" 41 . 42) (")" 42 . 43) (";" 43 . 44) (";" 45 . 47) (T_CLOSE_TAG 45 . 47) (T_INLINE_HTML 47 . 48))))) - ;; Nowdoc (phps-mode-test--with-buffer - "<?php echo <<<'MYLABEL'\nline 1\n line 2\nMYLABEL;\n" - nil + "<?php\n// Static variables\nfunction foo()\n{\n static $bar = <<<LABEL\nNothing in here...\nLABEL;\n}\n\n// Class properties/constants\nclass foo\n{\n const BAR = <<<FOOBAR\nConstant example\nFOOBAR;\n\n public $baz = <<<FOOBAR\nProperty example\nFOOBAR;\n}\n?>\n" + "Example #5 Using Heredoc to initialize static values" + (should (equal phps-mode-lex-analyzer--tokens + '((T_OPEN_TAG 1 . 7) (T_COMMENT 7 . 26) (T_FUNCTION 27 . 35) (T_STRING 36 . 39) ("(" 39 . 40) (")" 40 . 41) ("{" 42 . 43) (T_STATIC 48 . 54) (T_VARIABLE 55 . 59) ("=" 60 . 61) (T_START_HEREDOC 62 . 71) (T_ENCAPSED_AND_WHITESPACE 71 . 89) (T_END_HEREDOC 89 . 95) (";" 95 . 96) ("}" 97 . 98) (T_COMMENT 100 . 129) (T_CLASS 130 . 135) (T_STRING 136 . 139) ("{" 140 . 141) (T_CONST 146 . 151) (T_STRING 152 . 155) ("=" 156 . 157) (T_START_HEREDOC 158 . 168) (T_ENCAPSED_AND_WHIT [...] + + (phps-mode-test--with-buffer + "<?php\necho <<<\"FOOBAR\"\nHello World!\nFOOBAR;\n?>\n" + "Example #6 Using double quotes in Heredoc" + (should (equal phps-mode-lex-analyzer--tokens + '((T_OPEN_TAG 1 . 7) (T_ECHO 7 . 11) (T_START_HEREDOC 12 . 24) (T_ENCAPSED_AND_WHITESPACE 24 . 36) (T_END_HEREDOC 36 . 43) (";" 43 . 44) (";" 45 . 47) (T_CLOSE_TAG 45 . 47) (T_INLINE_HTML 47 . 48))))) + + ;; NOWDOC + + (phps-mode-test--with-buffer + "<?php\necho <<<'EOD'\nExample of string spanning multiple lines\nusing nowdoc syntax. Backslashes are always treated literally,\ne.g. \\ and \'.\nEOD;\n" + "Example #7 Nowdoc string quoting example" + (should (equal phps-mode-lex-analyzer--tokens + '((T_OPEN_TAG 1 . 7) (T_ECHO 7 . 11) (T_START_HEREDOC 12 . 21) (T_ENCAPSED_AND_WHITESPACE 21 . 139) (T_END_HEREDOC 139 . 143) (";" 143 . 144))))) + + (phps-mode-test--with-buffer + "<?php\nclass foo\n{\n public $foo;\n public $bar;\n\n function __construct()\n {\n $this->foo = 'Foo';\n $this->bar = array('Bar1', 'Bar2', 'Bar3');\n }\n}\n\n$foo = new foo();\n$name = 'MyName';\n\necho <<<'EOT'\nMy name is \"$name\". I am printing some $foo->foo.\nNow, I am printing some {$foo->bar[1]}.\nThis should not print a capital 'A': \x41\nEOT;\n?>\n" + "Example #8 Nowdoc string quoting example with variables" + (should (equal phps-mode-lex-analyzer--tokens + '((T_OPEN_TAG 1 . 7) (T_CLASS 7 . 12) (T_STRING 13 . 16) ("{" 17 . 18) (T_PUBLIC 23 . 29) (T_VARIABLE 30 . 34) (";" 34 . 35) (T_PUBLIC 40 . 46) (T_VARIABLE 47 . 51) (";" 51 . 52) (T_FUNCTION 58 . 66) (T_STRING 67 . 78) ("(" 78 . 79) (")" 79 . 80) ("{" 85 . 86) (T_VARIABLE 95 . 100) (T_OBJECT_OPERATOR 100 . 102) (T_STRING 102 . 105) ("=" 106 . 107) (T_CONSTANT_ENCAPSED_STRING 108 . 113) (";" 113 . 114) (T_VARIABLE 123 . 128) (T_OBJECT_OPERATOR 128 . 130) (T_STRING 130 . [...] + + (phps-mode-test--with-buffer + "<?php\nclass foo {\n public $bar = <<<'EOT'\nbar\nEOT;\n}\n?>\n" + "Example #9 Static data example (Nowdoc)" (should (equal phps-mode-lex-analyzer--tokens - '((T_OPEN_TAG 1 . 7) (T_ECHO 7 . 11) (T_START_HEREDOC 12 . 25) (T_ENCAPSED_AND_WHITESPACE 25 . 39) (T_END_HEREDOC 39 . 47) (";" 47 . 48))))) + '((T_OPEN_TAG 1 . 7) (T_CLASS 7 . 12) (T_STRING 13 . 16) ("{" 17 . 18) (T_PUBLIC 23 . 29) (T_VARIABLE 30 . 34) ("=" 35 . 36) (T_START_HEREDOC 37 . 46) (T_ENCAPSED_AND_WHITESPACE 46 . 49) (T_END_HEREDOC 49 . 53) (";" 53 . 54) ("}" 55 . 56) (";" 57 . 59) (T_CLOSE_TAG 57 . 59) (T_INLINE_HTML 59 . 60))))) ;; Backquotes (phps-mode-test--with-buffer