branch: externals/phps-mode
commit 620ec6eaeaa8bba8af0bd0a00e208d3c60f1f8fc
Author: Christian Johansson <[email protected]>
Commit: Christian Johansson <[email protected]>
Optimization of parser speed
---
phps-mode-automation-grammar.el | 126 +++++-----------------------------------
phps-mode-lex-analyzer.el | 53 ++++++++++++++++-
phps-mode-parser.el | 125 +++++----------------------------------
test/phps-mode-test-parser.el | 6 +-
4 files changed, 83 insertions(+), 227 deletions(-)
diff --git a/phps-mode-automation-grammar.el b/phps-mode-automation-grammar.el
index 4a390b0..5b2a7a4 100644
--- a/phps-mode-automation-grammar.el
+++ b/phps-mode-automation-grammar.el
@@ -25,10 +25,6 @@
;; Just to stop linter from complaining
-(defvar
- phps-mode-parser-position
- nil
- "Position of parser.")
(defvar
phps-mode-parser-tokens
@@ -52,7 +48,7 @@
(defvar
phps-mode-automation-grammar--header
- "\n\n(defvar-local\n phps-mode-parser-position\n nil\n \"Position of
parser.\")\n\n(defvar-local\n phps-mode-parser-tokens\n nil\n \"Tokens for
parser.\")\n\n(define-error\n 'phps-parser-error\n \"PHPs Lexer Error\")\n\n"
+ "\n\n(defvar-local\n phps-mode-parser-tokens\n nil\n \"Tokens for
parser.\")\n\n(define-error\n 'phps-parser-error\n \"PHPs Parser Error\")\n\n"
"Header contents for parser.")
(defvar
@@ -68,118 +64,26 @@
(defvar
phps-mode-automation-grammar--lex-analyzer-function
(lambda (buffer-index)
- (let ((token-list-index))
- (if (and
- phps-mode-parser-position
- (= (car (car phps-mode-parser-position)) buffer-index))
- (progn
- (setq
- token-list-index
- (car (cdr (car phps-mode-parser-position)))))
-
- ;; Search from last requested index and forward until
- ;; we find a token starting at or after buffer-index and
- ;; use this as buffer-index, save buffer-index to
- ;; token-list-index connection
- (let ((previous-token-list-index 0))
- (when (and
- phps-mode-parser-position
- (< (car (car phps-mode-parser-position)) buffer-index))
- (setq
- previous-token-list-index
- (car (cdr (car phps-mode-parser-position)))))
-
- (let ((temp-token-list-index
- previous-token-list-index)
- (token-list-size
- (length
- phps-mode-parser-tokens))
- (continue t))
- (while (and
- continue
- (<
- temp-token-list-index
- token-list-size))
- (let ((token
- (nth
- temp-token-list-index
- phps-mode-parser-tokens)))
-
- ;; When token starts at cursor we found correct index
- ;; Save it
- (when (= (car (cdr token)) buffer-index)
- (let ((token-type (car token)))
- (push
- (list
- buffer-index
- temp-token-list-index)
- phps-mode-parser-position)
- (unless (or
- (equal token-type 'T_OPEN_TAG)
- (equal token-type 'T_CLOSE_TAG)
- (equal token-type 'T_DOC_COMMENT)
- (equal token-type 'T_COMMENT))
- (setq
- token-list-index
- temp-token-list-index)
- (setq
- continue
- nil))))
-
- ;; When token starts after cursor, flag move of cursor
- ;; Save it
- (when (> (car (cdr token)) buffer-index)
- (let ((token-type (car token)))
- (push
- (list
- (car (cdr token))
- temp-token-list-index)
- phps-mode-parser-position)
-
- ;; Compatibility with parser
- (unless (or
- (equal token-type 'T_OPEN_TAG)
- (equal token-type 'T_DOC_COMMENT)
- (equal token-type 'T_COMMENT))
- (setq-local
- phps-mode-parser-lex-analyzer--move-to-index-flag
- (car (cdr token)))
- (setq
- continue
- nil))))
-
- (setq
- temp-token-list-index
- (1+ temp-token-list-index))
- )))))
- (when
- token-list-index
- (let ((token
- (nth
- token-list-index
- phps-mode-parser-tokens)))
-
- ;; Compatibility with parser
- (when (equal (car token) 'T_OPEN_TAG_WITH_ECHO)
- (setq
- token
- `(T_ECHO ,(car (cdr token)) . ,(cdr (cdr token)))))
- (when (equal (car token) 'T_CLOSE_TAG)
- (setq
- token
- `(";" ,(car (cdr token)) . ,(cdr (cdr token)))))
-
- token))))
+ (let ((result (gethash buffer-index phps-mode-parser-tokens))
+ (token))
+ (when result
+ (cond
+ ((numberp result)
+ (setq
+ phps-mode-parser-lex-analyzer--move-to-index-flag
+ result))
+ ((listp result)
+ (setq
+ token
+ result))))
+ token))
"The custom lex-analyzer.")
(defvar
phps-mode-automation-grammar--lex-analyzer-reset-function
(lambda()
(progn
- ;; Reset buffer-index to token-list-index connections
- (setq-local
- phps-mode-parser-position
- nil)))
+ ))
"The reset function.")
(defvar
diff --git a/phps-mode-lex-analyzer.el b/phps-mode-lex-analyzer.el
index ae707d8..7c68a4d 100644
--- a/phps-mode-lex-analyzer.el
+++ b/phps-mode-lex-analyzer.el
@@ -3196,6 +3196,50 @@ 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--generate-parser-tokens (lexer-tokens)
+ "Generate parser-tokens from LEXER-TOKENS which are in reversed order."
+ (let ((parser-tokens (make-hash-table :test 'equal))
+ (previous-start))
+ (dolist (token lexer-tokens)
+ (let ((token-type (car token))
+ (token-start (car (cdr token)))
+ (token-end (cdr (cdr token))))
+ (if (or
+ (equal token-type 'T_OPEN_TAG)
+ (equal token-type 'T_DOC_COMMENT)
+ (equal token-type 'T_COMMENT))
+ (when previous-start
+ (puthash
+ token-start
+ previous-start
+ parser-tokens))
+ (cond
+ ((equal token-type 'T_CLOSE_TAG)
+ (setq
+ token
+ `(";" ,token-start . ,token-end)))
+ ((equal token-type 'T_OPEN_TAG_WITH_ECHO)
+ (setq
+ token
+ `(T_ECHO ,token-start . ,token-end))))
+ (puthash
+ token-start
+ token
+ parser-tokens))
+
+ (when (and
+ previous-start
+ (not
+ (= previous-start token-end)))
+ (puthash
+ token-end
+ previous-start
+ parser-tokens))
+ (setq
+ previous-start
+ token-start)))
+ parser-tokens))
+
(defun phps-mode-lex-analyzer--lex-string (contents &optional start end states
state state-stack heredoc-label heredoc-label-stack nest-location-stack tokens)
"Run lexer on CONTENTS."
;; Create a separate buffer, run lexer inside of it, catch errors and return
them
@@ -3261,15 +3305,18 @@ SQUARE-BRACKET-LEVEL and ROUND-BRACKET-LEVEL."
(setq state phps-mode-lexer--state)
(setq state-stack phps-mode-lexer--state-stack)
(setq states phps-mode-lexer--states)
+
+ ;; NOTE Generate parser tokens here before nreverse destructs list
+ (setq
+ phps-mode-parser-tokens
+ (phps-mode-lex-analyzer--generate-parser-tokens
+ phps-mode-lexer--generated-tokens))
(setq tokens (nreverse phps-mode-lexer--generated-tokens))
(setq heredoc-label phps-mode-lexer--heredoc-label)
(setq heredoc-label-stack phps-mode-lexer--heredoc-label-stack)
(setq nest-location-stack phps-mode-lexer--nest-location-stack)
;; Error-free parse here
- (setq
- phps-mode-parser-tokens
- tokens)
(condition-case conditions
(progn
(setq
diff --git a/phps-mode-parser.el b/phps-mode-parser.el
index 09b976e..e914eeb 100644
--- a/phps-mode-parser.el
+++ b/phps-mode-parser.el
@@ -8,18 +8,13 @@
(defvar-local
- phps-mode-parser-position
- nil
- "Position of parser.")
-
-(defvar-local
phps-mode-parser-tokens
nil
"Tokens for parser.")
(define-error
'phps-parser-error
- "PHPs Lexer Error")
+ "PHPs Parser Error")
;;; Constants:
@@ -111,118 +106,26 @@
(defvar
phps-mode-parser-lex-analyzer--function
(lambda (buffer-index)
- (let ((token-list-index))
- (if (and
- phps-mode-parser-position
- (= (car (car phps-mode-parser-position)) buffer-index))
- (progn
- (setq
- token-list-index
- (car (cdr (car phps-mode-parser-position)))))
-
- ;; Search from last requested index and forward until
- ;; we find a token starting at or after buffer-index and
- ;; use this as buffer-index, save buffer-index to
- ;; token-list-index connection
- (let ((previous-token-list-index 0))
- (when (and
- phps-mode-parser-position
- (< (car (car phps-mode-parser-position)) buffer-index))
- (setq
- previous-token-list-index
- (car (cdr (car phps-mode-parser-position)))))
-
- (let ((temp-token-list-index
- previous-token-list-index)
- (token-list-size
- (length
- phps-mode-parser-tokens))
- (continue t))
- (while (and
- continue
- (<
- temp-token-list-index
- token-list-size))
- (let ((token
- (nth
- temp-token-list-index
- phps-mode-parser-tokens)))
-
- ;; When token starts at cursor we found correct index
- ;; Save it
- (when (= (car (cdr token)) buffer-index)
- (let ((token-type (car token)))
- (push
- (list
- buffer-index
- temp-token-list-index)
- phps-mode-parser-position)
- (unless (or
- (equal token-type 'T_OPEN_TAG)
- (equal token-type 'T_CLOSE_TAG)
- (equal token-type 'T_DOC_COMMENT)
- (equal token-type 'T_COMMENT))
- (setq
- token-list-index
- temp-token-list-index)
- (setq
- continue
- nil))))
-
- ;; When token starts after cursor, flag move of cursor
- ;; Save it
- (when (> (car (cdr token)) buffer-index)
- (let ((token-type (car token)))
- (push
- (list
- (car (cdr token))
- temp-token-list-index)
- phps-mode-parser-position)
-
- ;; Compatibility with parser
- (unless (or
- (equal token-type 'T_OPEN_TAG)
- (equal token-type 'T_DOC_COMMENT)
- (equal token-type 'T_COMMENT))
- (setq-local
- phps-mode-parser-lex-analyzer--move-to-index-flag
- (car (cdr token)))
- (setq
- continue
- nil))))
-
- (setq
- temp-token-list-index
- (1+ temp-token-list-index))
- )))))
- (when
- token-list-index
- (let ((token
- (nth
- token-list-index
- phps-mode-parser-tokens)))
-
- ;; Compatibility with parser
- (when (equal (car token) 'T_OPEN_TAG_WITH_ECHO)
- (setq
- token
- `(T_ECHO ,(car (cdr token)) . ,(cdr (cdr token)))))
- (when (equal (car token) 'T_CLOSE_TAG)
+ (let ((result (gethash buffer-index phps-mode-parser-tokens))
+ (token))
+ (when result
+ (cond
+ ((numberp result)
(setq
- token
- `(";" ,(car (cdr token)) . ,(cdr (cdr token)))))
-
- token))))
+ phps-mode-parser-lex-analyzer--move-to-index-flag
+ result))
+ ((listp result)
+ (setq
+ token
+ result))))
+ token))
"The lex-analyzer function.")
(defvar
phps-mode-parser-lex-analyzer--reset-function
(lambda()
(progn
- ;; Reset buffer-index to token-list-index connections
- (setq-local
- phps-mode-parser-position
- nil)))
+ ))
"The lex-analyzer reset function.")
diff --git a/test/phps-mode-test-parser.el b/test/phps-mode-test-parser.el
index a852a63..ca3f951 100644
--- a/test/phps-mode-test-parser.el
+++ b/test/phps-mode-test-parser.el
@@ -72,8 +72,10 @@
(semantic-lex-buffer)
(setq
phps-mode-parser-tokens
- (reverse phps-mode-lexer--generated-tokens))
- (message "Lexer tokens:\n%S\n" phps-mode-parser-tokens)
+ (phps-mode-lex-analyzer--generate-parser-tokens
+ phps-mode-lexer--generated-tokens))
+ (message "Lexer tokens:\n%S\n" phps-mode-lexer--generated-tokens)
+ (message "Parser tokens:\n%S\n" phps-mode-parser-tokens)
;; Run test
(funcall logic)