branch: externals/phps-mode commit ff28d3c3910233135b42a78c821f8f33e12a157d Author: Christian Johansson <christ...@cvj.se> Commit: Christian Johansson <christ...@cvj.se>
Fixed bug in incremental lex-analyzer related to heredoc and nesting stack --- Makefile | 9 +- admin/phps-mode-automation-header.wy | 312 ----------------------------------- admin/phps-mode-automation.el | 117 ++++++------- phps-mode-lex-analyzer.el | 38 ++++- phps-mode-lexer.el | 20 ++- phps-mode.el | 4 +- test/phps-mode-test-integration.el | 153 ++--------------- test/phps-mode-test-lexer.el | 48 +++--- 8 files changed, 152 insertions(+), 549 deletions(-) diff --git a/Makefile b/Makefile index 2a6e1ee..9c1b246 100644 --- a/Makefile +++ b/Makefile @@ -2,15 +2,19 @@ EMACS = emacs ifdef emacs EMACS = $(emacs) endif -EMACS_CMD := $(EMACS) -Q -batch -L . -L test/ +EMACS_CMD := $(EMACS) -Q -batch -L . -L test/ -L admin/ -EL := admin/phps-mode-automation.el phps-mode-flymake.el phps-mode-lex-analyzer.el phps-mode-lexer.el phps-mode-macros.el phps-mode-syntax-table.el phps-mode-parser-grammar-macro.el phps-mode.el phps-mode-test.el test/phps-mode-test-lex-analyzer.el test/phps-mode-test-integration.el test/phps-mode-test-lexer.el test/phps-mode-test-parser.el test/phps-mode-test-syntax-table.el +EL := admin/phps-mode-automation.el admin/phps-mode-automation-grammar.el phps-mode-flymake.el phps-mode-lex-analyzer.el phps-mode-lexer.el phps-mode-macros.el phps-mode-syntax-table.el phps-mode-parser-grammar-macro.el phps-mode.el phps-mode-test.el test/phps-mode-test-lex-analyzer.el test/phps-mode-test-integration.el test/phps-mode-test-lexer.el test/phps-mode-test-parser.el test/phps-mode-test-syntax-table.el ELC := $(EL:.el=.elc) .PHONY: clean clean: rm -f $(ELC) +.PHONY: generate-parser +generate-parser: + $(EMACS_CMD) -L ~/.emacs.d/emacs-parser-generator/ -l phps-mode-lexer.el -l admin/phps-mode-automation.el + .PHONY: compile compile: $(EMACS_CMD) -f batch-byte-compile $(EL) @@ -26,7 +30,6 @@ test-integration: test-lex-analyzer: $(EMACS_CMD) -l test/phps-mode-test-lex-analyzer.el - .PHONY: test-lexer test-lexer: $(EMACS_CMD) -l test/phps-mode-test-lexer.el -f "phps-mode-test-lexer" diff --git a/admin/phps-mode-automation-header.wy b/admin/phps-mode-automation-header.wy deleted file mode 100644 index 17c4b33..0000000 --- a/admin/phps-mode-automation-header.wy +++ /dev/null @@ -1,312 +0,0 @@ -;;; phps.wy --- Semantic LALR grammar for PHP -*- lexical-binding: t -*- - -;; Copyright (C) 2018-2020 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: - -;; Run `(wisent-make-parsers)' or "C-c C-c" to generate grammar-file in Emacs Lisp. -;; -;; To debug (setq wisent-verbose-flag t) and check buffer *wisent-log* -;; -;; Based on the Zend PHP Parser YACC https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y - -;; Create macros for all macros uses in original YACC, base macro structure on semantic-php-wy-macro.el - -;; Don't edit phps.wy because it's generated by phps-automation.el and phps-automation-header.wy - -;; Check semantic/wisent/grammar.el for macro definitions - -;; To force compile grammar use: (semantic-grammar-create-package t) - - -;;; Code: - -%package phps-mode -%provide phps-mode-wy - -%languagemode phps-mode - -%{ - (setq max-specpdl-size 160000) -} - -%use-macros phps-mode-parser-grammar-macro -{ - ZEND_AST_CREATE - ZEND_AST_CREATE_ASSIGN_OP - ZEND_AST_CREATE_BINARY_OP - ZEND_AST_CREATE_CAST - ZEND_AST_CREATE_CLASS_CONST_OR_NAME - ZEND_AST_CREATE_EX - ZEND_AST_CREATE_LIST - ZEND_AST_CREATE_ZVAL - ZEND_AST_LIST_ADD - ZEND_AST_LIST_RTRIM - ZEND_LEX_TSTRING - ZEND_NEGATE_NUM_STRING - ZVAL_INTERNED_STR -} - -%precedence T_THROW -%precedence PREC_ARROW_FUNCTION -%precedence T_INCLUDE T_INCLUDE_ONCE T_REQUIRE T_REQUIRE_ONCE -%left T_LOGICAL_OR -%left T_LOGICAL_XOR -%left T_LOGICAL_AND -%precedence T_PRINT -%precedence T_YIELD -%precedence T_DOUBLE_ARROW -%precedence T_YIELD_FROM -%precedence '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL T_COALESCE_EQUAL -%left '?' ':' -%right T_COALESCE -%left T_BOOLEAN_OR -%left T_BOOLEAN_AND -%left '|' -%left '^' -%left '&' -%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP -%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL -%left '.' -%left T_SL T_SR -%left '+' '-' -%left '*' '/' '%' -%precedence '!' -%precedence T_INSTANCEOF -%precedence '~' T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' -%right T_POW -%precedence T_CLONE - -;; Resolve danging else conflict -%precedence T_NOELSE -%precedence T_ELSEIF -%precedence T_ELSE - -%token <ast> T_LNUMBER "integer number (T_LNUMBER)" -%token <ast> T_DNUMBER "floating-point number (T_DNUMBER)" -%token <ast> T_STRING "identifier (T_STRING)" -%token <ast> T_VARIABLE "variable (T_VARIABLE)" -%token <ast> T_INLINE_HTML -%token <ast> T_ENCAPSED_AND_WHITESPACE "quoted-string and whitespace (T_ENCAPSED_AND_WHITESPACE)" -%token <ast> T_CONSTANT_ENCAPSED_STRING "quoted-string (T_CONSTANT_ENCAPSED_STRING)" -%token <ast> T_STRING_VARNAME "variable name (T_STRING_VARNAME)" -%token <ast> T_NUM_STRING "number (T_NUM_STRING)" - -%type <punctuation> -%token <punctuation> ADDITION "+" -%token <punctuation> ASSIGN "=" -%token <punctuation> AT "@" -%token <punctuation> BACKTICK "`" -%token <punctuation> BITWISE_AND "&" -%token <punctuation> BITWISE_OR "|" -%token <punctuation> CLOSE_CURLY_BRACKET "]" -%token <punctuation> CLOSE_PARENTHESIS ")" -%token <punctuation> CLOSE_SQUARE_BRACKET "]" -%token <punctuation> COLON ":" -%token <punctuation> COMMA "," -%token <punctuation> DOLLAR_SIGN "$" -%token <punctuation> DOUBLE_QUOTE "\"" -%token <punctuation> DIVISION "/" -%token <punctuation> DOT "." -%token <punctuation> GREATER_THAN ">" -%token <punctuation> LESSER_THAN "<" -%token <punctuation> MODULO "%" -%token <punctuation> MULTIPLICATION "*" -%token <punctuation> NEGATION "!" -%token <punctuation> OPEN_CURLY_BRACKET "{" -%token <punctuation> OPEN_PARENTHESIS "(" -%token <punctuation> OPEN_SQUARE_BRACKET "[" -%token <punctuation> POW "^" -%token <punctuation> QUESTION_MARK "?" -%token <punctuation> SEMICOLON ";" -%token <punctuation> SINGLE_QUOTE "'" -%token <punctuation> SUBTRACTION "-" -%token <punctuation> UNARY "~" - -%token END 0 "end of file" -%token T_INCLUDE "include (T_INCLUDE)" -%token T_INCLUDE_ONCE "include_once (T_INCLUDE_ONCE)" -%token T_EVAL "eval (T_EVAL)" -%token T_REQUIRE "require (T_REQUIRE)" -%token T_REQUIRE_ONCE "require_once (T_REQUIRE_ONCE)" -%token T_LOGICAL_OR "or (T_LOGICAL_OR)" -%token T_LOGICAL_XOR "xor (T_LOGICAL_XOR)" -%token T_LOGICAL_AND "and (T_LOGICAL_AND)" -%token T_PRINT "print (T_PRINT)" -%token T_YIELD "yield (T_YIELD)" -%token T_YIELD_FROM "yield from (T_YIELD_FROM)" -%token T_PLUS_EQUAL "+= (T_PLUS_EQUAL)" -%token T_MINUS_EQUAL "-= (T_MINUS_EQUAL)" -%token T_MUL_EQUAL "*= (T_MUL_EQUAL)" -%token T_DIV_EQUAL "/= (T_DIV_EQUAL)" -%token T_CONCAT_EQUAL ".= (T_CONCAT_EQUAL)" -%token T_MOD_EQUAL "%= (T_MOD_EQUAL)" -%token T_AND_EQUAL "&= (T_AND_EQUAL)" -%token T_OR_EQUAL "|= (T_OR_EQUAL)" -%token T_XOR_EQUAL "^= (T_XOR_EQUAL)" -%token T_SL_EQUAL "<<= (T_SL_EQUAL)" -%token T_SR_EQUAL ">>= (T_SR_EQUAL)" -%token T_COALESCE_EQUAL "??= (T_COALESCE_EQUAL)" -%token T_BOOLEAN_OR "|| (T_BOOLEAN_OR)" -%token T_BOOLEAN_AND "&& (T_BOOLEAN_AND)" -%token T_IS_EQUAL "== (T_IS_EQUAL)" -%token T_IS_NOT_EQUAL "!= (T_IS_NOT_EQUAL)" -%token T_IS_IDENTICAL "=== (T_IS_IDENTICAL)" -%token T_IS_NOT_IDENTICAL "!== (T_IS_NOT_IDENTICAL)" -%token T_IS_SMALLER_OR_EQUAL "<= (T_IS_SMALLER_OR_EQUAL)" -%token T_IS_GREATER_OR_EQUAL ">= (T_IS_GREATER_OR_EQUAL)" -%token T_SPACESHIP "<=> (T_SPACESHIP)" -%token T_SL "<< (T_SL)" -%token T_SR ">> (T_SR)" -%token T_INSTANCEOF "instanceof (T_INSTANCEOF)" -%token T_INC "++ (T_INC)" -%token T_DEC "-- (T_DEC)" -%token T_INT_CAST "(int) (T_INT_CAST)" -%token T_DOUBLE_CAST "(double) (T_DOUBLE_CAST)" -%token T_STRING_CAST "(string) (T_STRING_CAST)" -%token T_ARRAY_CAST "(array) (T_ARRAY_CAST)" -%token T_OBJECT_CAST "(object) (T_OBJECT_CAST)" -%token T_BOOL_CAST "(bool) (T_BOOL_CAST)" -%token T_UNSET_CAST "(unset) (T_UNSET_CAST)" -%token T_NEW "new (T_NEW)" -%token T_CLONE "clone (T_CLONE)" -%token T_EXIT "exit (T_EXIT)" -%token T_IF "if (T_IF)" -%token T_ELSEIF "elseif (T_ELSEIF)" -%token T_ELSE "else (T_ELSE)" -%token T_ENDIF "endif (T_ENDIF)" -%token T_ECHO "echo (T_ECHO)" -%token T_DO "do (T_DO)" -%token T_WHILE "while (T_WHILE)" -%token T_ENDWHILE "endwhile (T_ENDWHILE)" -%token T_FOR "for (T_FOR)" -%token T_ENDFOR "endfor (T_ENDFOR)" -%token T_FOREACH "foreach (T_FOREACH)" -%token T_ENDFOREACH "endforeach (T_ENDFOREACH)" -%token T_DECLARE "declare (T_DECLARE)" -%token T_ENDDECLARE "enddeclare (T_ENDDECLARE)" -%token T_AS "as (T_AS)" -%token T_SWITCH "switch (T_SWITCH)" -%token T_ENDSWITCH "endswitch (T_ENDSWITCH)" -%token T_CASE "case (T_CASE)" -%token T_DEFAULT "default (T_DEFAULT)" -%token T_BREAK "break (T_BREAK)" -%token T_CONTINUE "continue (T_CONTINUE)" -%token T_GOTO "goto (T_GOTO)" -%token T_FUNCTION "function (T_FUNCTION)" -%token T_FN "fn (T_FN)" -%token T_CONST "const (T_CONST)" -%token T_RETURN "return (T_RETURN)" -%token T_TRY "try (T_TRY)" -%token T_CATCH "catch (T_CATCH)" -%token T_FINALLY "finally (T_FINALLY)" -%token T_THROW "throw (T_THROW)" -%token T_USE "use (T_USE)" -%token T_INSTEADOF "insteadof (T_INSTEADOF)" -%token T_GLOBAL "global (T_GLOBAL)" -%token T_STATIC "static (T_STATIC)" -%token T_ABSTRACT "abstract (T_ABSTRACT)" -%token T_FINAL "final (T_FINAL)" -%token T_PRIVATE "private (T_PRIVATE)" -%token T_PROTECTED "protected (T_PROTECTED)" -%token T_PUBLIC "public (T_PUBLIC)" -%token T_VAR "var (T_VAR)" -%token T_UNSET "unset (T_UNSET)" -%token T_ISSET "isset (T_ISSET)" -%token T_EMPTY "empty (T_EMPTY)" -%token T_HALT_COMPILER "__halt_compiler (T_HALT_COMPILER)" -%token T_CLASS "class (T_CLASS)" -%token T_TRAIT "trait (T_TRAIT)" -%token T_INTERFACE "interface (T_INTERFACE)" -%token T_EXTENDS "extends (T_EXTENDS)" -%token T_IMPLEMENTS "implements (T_IMPLEMENTS)" -%token T_OBJECT_OPERATOR "-> (T_OBJECT_OPERATOR)" -%token T_DOUBLE_ARROW "=> (T_DOUBLE_ARROW)" -%token T_LIST "list (T_LIST)" -%token T_ARRAY "array (T_ARRAY)" -%token T_CALLABLE "callable (T_CALLABLE)" -%token T_LINE "__LINE__ (T_LINE)" -%token T_FILE "__FILE__ (T_FILE)" -%token T_DIR "__DIR__ (T_DIR)" -%token T_CLASS_C "__CLASS__ (T_CLASS_C)" -%token T_TRAIT_C "__TRAIT__ (T_TRAIT_C)" -%token T_METHOD_C "__METHOD__ (T_METHOD_C)" -%token T_FUNC_C "__FUNCTION__ (T_FUNC_C)" -%token T_COMMENT "comment (T_COMMENT)" -%token T_DOC_COMMENT "doc comment (T_DOC_COMMENT)" -%token T_OPEN_TAG "open tag (T_OPEN_TAG)" -%token T_OPEN_TAG_WITH_ECHO "open tag with echo (T_OPEN_TAG_WITH_ECHO)" -%token T_CLOSE_TAG "close tag (T_CLOSE_TAG)" -%token T_WHITESPACE "whitespace (T_WHITESPACE)" -%token T_START_HEREDOC "heredoc start (T_START_HEREDOC)" -%token T_END_HEREDOC "heredoc end (T_END_HEREDOC)" -%token T_DOLLAR_OPEN_CURLY_BRACES "${ (T_DOLLAR_OPEN_CURLY_BRACES)" -%token T_CURLY_OPEN "{$ (T_CURLY_OPEN)" -%token T_PAAMAYIM_NEKUDOTAYIM ":: (T_PAAMAYIM_NEKUDOTAYIM)" -%token T_NAMESPACE "namespace (T_NAMESPACE)" -%token T_NS_C "__NAMESPACE__ (T_NS_C)" -%token T_NS_SEPARATOR "\\ (T_NS_SEPARATOR)" -%token T_ELLIPSIS "... (T_ELLIPSIS)" -%token T_COALESCE "?? (T_COALESCE)" -%token T_POW "** (T_POW)" -%token T_POW_EQUAL "**= (T_POW_EQUAL)" -%token T_BAD_CHARACTER "invalid character (T_BAD_CHARACTER)" - -;; Token used to force a parse error from the lexer -%token T_ERROR - -%type <ast> top_statement namespace_name name statement function_declaration_statement -%type <ast> class_declaration_statement trait_declaration_statement -%type <ast> interface_declaration_statement interface_extends_list -%type <ast> group_use_declaration inline_use_declarations inline_use_declaration -%type <ast> mixed_group_use_declaration use_declaration unprefixed_use_declaration -%type <ast> unprefixed_use_declarations const_decl inner_statement -%type <ast> expr optional_expr while_statement for_statement foreach_variable -%type <ast> foreach_statement declare_statement finally_statement unset_variable variable -%type <ast> extends_from parameter optional_type_without_static argument global_var -%type <ast> static_var class_statement trait_adaptation trait_precedence trait_alias -%type <ast> absolute_trait_method_reference trait_method_reference property echo_expr -%type <ast> new_expr anonymous_class class_name class_name_reference simple_variable -%type <ast> internal_functions_in_yacc -%type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name property_name -%type <ast> variable_class_name dereferencable_scalar constant class_constant -%type <ast> fully_dereferencable array_object_dereferencable -%type <ast> callable_expr callable_variable static_member new_variable -%type <ast> encaps_var encaps_var_offset isset_variables -%type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt -%type <ast> alt_if_stmt for_exprs switch_case_list global_var_list static_var_list -%type <ast> echo_expr_list unset_variables catch_name_list catch_list optional_variable parameter_list class_statement_list -%type <ast> implements_list case_list if_stmt_without_else -%type <ast> non_empty_parameter_list argument_list non_empty_argument_list property_list -%type <ast> class_const_list class_const_decl class_name_list trait_adaptations method_body non_empty_for_exprs -%type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars -%type <ast> lexical_var_list encaps_list -%type <ast> array_pair non_empty_array_pair_list array_pair_list possible_array_pair -%type <ast> isset_variable type return_type type_expr type_without_static -%type <ast> identifier type_expr_without_static union_type_without_static -%type <ast> inline_function union_type - -%type <num> returns_ref function fn is_reference is_variadic variable_modifiers -%type <num> method_modifiers non_empty_member_modifiers member_modifier -%type <num> class_modifiers class_modifier use_type backup_fn_flags - -%type <ptr> backup_lex_pos -%type <str> backup_doc_comment - -%start start \ No newline at end of file diff --git a/admin/phps-mode-automation.el b/admin/phps-mode-automation.el index d4ff671..39ce0ff 100644 --- a/admin/phps-mode-automation.el +++ b/admin/phps-mode-automation.el @@ -1,4 +1,4 @@ -;;; phps-automation --- Generate a Wisent Parser file -*- lexical-binding: t -*- +;;; phps-mode-automation --- Generate a Wisent Parser file -*- lexical-binding: t -*- ;; Copyright (C) 2018-2021 Free Software Foundation, Inc. @@ -27,61 +27,66 @@ ;;; Code: -(let ((php-yacc-url "https://raw.githubusercontent.com/php/php-src/master/Zend/zend_language_parser.y") - (php-yacc-file (expand-file-name "zend_language_parser.y")) - (wisent-destination (expand-file-name "../phps-mode-parser-grammar-raw.wy")) - (header (expand-file-name "phps-mode-automation-header.wy")) - (terminal-replacements (make-hash-table :test 'equal))) - - (puthash "'+'" "ADDITION" terminal-replacements) - (puthash "'='" "ASSIGN" terminal-replacements) - (puthash "'@'" "AT" terminal-replacements) - (puthash "'`'" "BACKTICK" terminal-replacements) - (puthash "'&'" "BITWISE_AND" terminal-replacements) - (puthash "'|'" "BITWISE_OR" terminal-replacements) - (puthash "'}'" "CLOSE_CURLY_BRACKET" terminal-replacements) - (puthash "')'" "CLOSE_PARENTHESIS" terminal-replacements) - (puthash "']'" "CLOSE_SQUARE_BRACKET" terminal-replacements) - (puthash "':'" "COLON" terminal-replacements) - (puthash "','" "COMMA" terminal-replacements) - (puthash "'$'" "DOLLAR_SIGN" terminal-replacements) - (puthash "'\"'" "DOUBLE_QUOTE" terminal-replacements) - (puthash "'/'" "DIVISION" terminal-replacements) - (puthash "'.'" "DOT" terminal-replacements) - (puthash "'>'" "GREATER_THAN" terminal-replacements) - (puthash "'<'" "LESSER_THAN" terminal-replacements) - (puthash "'%'" "MODULO" terminal-replacements) - (puthash "'*'" "MULTIPLICATION" terminal-replacements) - (puthash "'!'" "NEGATION" terminal-replacements) - (puthash "'{'" "OPEN_CURLY_BRACKET" terminal-replacements) - (puthash "'('" "OPEN_PARENTHESIS" terminal-replacements) - (puthash "'['" "OPEN_SQUARE_BRACKET" terminal-replacements) - (puthash "'^'" "POW" terminal-replacements) - (puthash "'?'" "QUESTION_MARK" terminal-replacements) - (puthash "';'" "SEMICOLON" terminal-replacements) - (puthash "'''" "SINGLE_QUOTE" terminal-replacements) - (puthash "'-'" "SUBTRACTION" terminal-replacements) - (puthash "'~'" "UNARY" terminal-replacements) - - ;; Download Yacc if not available - (unless (file-exists-p php-yacc-file) - (message "Downloading PHP Yacc grammar..") - (url-copy-file php-yacc-url php-yacc-file t t) - (message "Download completed")) - - ;; Generate grammar - (message "Generating Wisent grammar..") - (if (fboundp 'emacs-wisent-grammar-converter--generate-grammar-from-filename) - (emacs-wisent-grammar-converter--generate-grammar-from-filename - php-yacc-file - wisent-destination - header - "phps-mode-parser--" - terminal-replacements) - (display-warning - 'warning - "Missing emacs-wisent-grammar-converter!")) - (message "Automation completed")) +(require 'phps-mode-automation-grammar) + +(when (fboundp 'parser-generator-lr-export-to-elisp) + + (let ((php-yacc-url "https://raw.githubusercontent.com/php/php-src/php-8.0.0/Zend/zend_language_parser.y") + (php-yacc-file (expand-file-name "zend_language_parser.y"))) + + ;; Download Yacc if not available + (unless (file-exists-p php-yacc-file) + (message "Downloading PHP 8.0 YACC grammar..") + (url-copy-file php-yacc-url php-yacc-file t t) + (message "Download of PHP 8.0 YACC grammar completed")) + + ;; Prepare export + (when (fboundp 'parser-generator-set-grammar) + (parser-generator-set-grammar + `( + ,phps-mode-automation-grammar-non-terminals + ,phps-mode-automation-grammar-terminals + ,phps-mode-automation-grammar-productions + ,phps-mode-automation-grammar-start + ) + )) + (when (fboundp 'parser-generator-set-look-ahead-number) + (parser-generator-set-look-ahead-number + phps-mode-automation-grammar-look-ahead-number)) + (when (boundp 'parser-generator--e-identifier) + (setq + parser-generator--e-identifier + phps-mode-automation-grammar-e-identifier)) + (when (boundp 'parser-generator--eof-identifier) + (setq + parser-generator--eof-identifier + phps-mode-automation-grammar-eof-identifier)) + (when (boundp 'parser-generator-lex-analyzer--function) + (setq + parser-generator-lex-analyzer--function + phps-mode-automation-grammar-lex-analyzer-function)) + (when (boundp 'parser-generator-lex-analyzer--get-function) + (setq + parser-generator-lex-analyzer--get-function + phps-mode-automation-grammar-lex-analyzer-get-function)) + (when (boundp 'parser-generator-lr--precedence-attribute) + (setq + parser-generator-lr--precedence-attribute + phps-mode-automation-grammar-precendece-attribute)) + (when (boundp 'parser-generator-lr--precedence-comparison-function) + (setq + parser-generator-lr--precedence-comparison-function + phps-mode-automation-grammar-precedence-comparison-function)) + (when (fboundp 'parser-generator-process-grammar) + (parser-generator-process-grammar)) + (when (fboundp 'parser-generator-lr-generate-parser-tables) + (parser-generator-lr-generate-parser-tables)) + + ;; Export + (let ((export (parser-generator-lr-export-to-elisp "phps-mode-parser"))) + (message "export: %s" export)) + + (message "Automation completed"))) (provide 'phps-mode-automation) ;;; phps-mode-automation.el ends here diff --git a/phps-mode-lex-analyzer.el b/phps-mode-lex-analyzer.el index ed66b6d..c340072 100644 --- a/phps-mode-lex-analyzer.el +++ b/phps-mode-lex-analyzer.el @@ -578,7 +578,11 @@ (defun phps-mode-lex-analyzer--move-states (start diff) "Move lexer states after (or equal to) START with modification DIFF." (when phps-mode-lex-analyzer--states - (setq phps-mode-lex-analyzer--states (phps-mode-lex-analyzer--get-moved-states phps-mode-lex-analyzer--states start diff)))) + (setq phps-mode-lex-analyzer--states + (phps-mode-lex-analyzer--get-moved-states + phps-mode-lex-analyzer--states + start + diff)))) (defun phps-mode-lex-analyzer--get-moved-states (states start diff) "Return moved lexer STATES after (or equal to) START with modification DIFF." @@ -591,16 +595,38 @@ (let ((state-start (nth 0 state-object)) (state-end (nth 1 state-object)) (state-symbol (nth 2 state-object)) - (state-stack (nth 3 state-object))) + (state-stack (nth 3 state-object)) + (heredoc-label (nth 4 state-object)) + (heredoc-label-stack (nth 5 state-object)) + (nest-location-stack (nth 6 state-object))) (if (>= state-start start) (let ((new-state-start (+ state-start diff)) (new-state-end (+ state-end diff))) - (push (list new-state-start new-state-end state-symbol state-stack) new-states)) + (push + (list + new-state-start + new-state-end + state-symbol + state-stack + heredoc-label + heredoc-label-stack + nest-location-stack) + new-states)) (if (> state-end start) (let ((new-state-end (+ state-end diff))) - (push (list state-start new-state-end state-symbol state-stack) new-states)) - (push state-object new-states)))))) - + (push + (list + state-start + new-state-end + state-symbol + state-stack + heredoc-label + heredoc-label-stack + nest-location-stack) + new-states)) + (push + state-object + new-states)))))) new-states)) (defun phps-mode-lex-analyzer--move-tokens (start diff) diff --git a/phps-mode-lexer.el b/phps-mode-lexer.el index 358d8b3..46bbc73 100644 --- a/phps-mode-lexer.el +++ b/phps-mode-lexer.el @@ -117,6 +117,9 @@ (defvar-local phps-mode-lexer--generated-tokens nil "List of current generated tokens.") +(defvar-local phps-mode-lexer--generated-new-tokens nil + "List of current newly generated tokens.") + (defvar-local phps-mode-lexer--state nil "Current state of lexer.") @@ -218,7 +221,7 @@ "Entered nesting '%s'" opening)) (push - opening + `(,opening ,(point)) phps-mode-lexer--nest-location-stack)) (defun phps-mode-lexer--handle-newline () @@ -240,16 +243,21 @@ (when (and opening (or - (and (string= opening "{") + (and (string= (car opening) "{") (not (string= closing "}"))) - (and (string= opening "[") + (and (string= (car opening) "[") (not (string= closing "]"))) - (and (string= opening "(") + (and (string= (car opening) "(") (not (string= closing ")"))))) (signal 'phps-lexer-error (list - (format "Bad nesting '%s' vs '%s' at %d'" opening closing (point)) + (format + "Bad nesting '%s' started at '%s' vs '%s' at %d'" + (car opening) + (car (cdr opening)) + closing + (point)) (point)))) (phps-mode-debug-message (message @@ -271,6 +279,7 @@ (semantic-lex-push-token (semantic-lex-token token start end)) (push `(,token ,start . ,end) phps-mode-lexer--generated-tokens) + (push `(,token ,start . ,end) phps-mode-lexer--generated-new-tokens) (phps-mode-debug-message (message @@ -461,6 +470,7 @@ (defun phps-mode-lexer--re2c () "Elisp port of original Zend re2c lexer." + (setq phps-mode-lexer--generated-new-tokens nil) (setq phps-mode-lexer--restart-flag nil) (let ((old-start (point))) (phps-mode-debug-message diff --git a/phps-mode.el b/phps-mode.el index cbab269..e401459 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: 29 Jan 2021 -;; Version: 0.4.1 +;; Modified: 10 Mars 2021 +;; Version: 0.4.2 ;; 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 0a8e90e..214882f 100644 --- a/test/phps-mode-test-integration.el +++ b/test/phps-mode-test-integration.el @@ -169,155 +169,26 @@ (goto-char 88) (delete-char 1)) - ) - -(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-lex-analyzer--tokens) - ;; (message "States: %s" phps-mode-lex-analyzer--states) - - ;; Initial state - - ;; Tokens - (should (equal phps-mode-lex-analyzer--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-lex-analyzer--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-lex-analyzer--tokens) - ;; (message "States: %s" phps-mode-lex-analyzer--states) - (phps-mode-lex-analyzer--process-changes) - ;; (message "Tokens %s" phps-mode-lex-analyzer--tokens) - ;; (message "States: %s" phps-mode-lex-analyzer--states) - - ;; Tokens - (should (equal phps-mode-lex-analyzer--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-lex-analyzer--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-lex-analyzer--tokens) - ;; (message "States: %s" phps-mode-lex-analyzer--states) - - ;; Initial state - - ;; Tokens - (should (equal phps-mode-lex-analyzer--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-lex-analyzer--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-lex-analyzer--process-changes) - - ;; Final state - ;; (message "Modified buffer: '%s'" (buffer-substring-no-properties (point-min) (point-max))) - ;; (message "Tokens %s" phps-mode-lex-analyzer--tokens) - ;; (message "States: %s" phps-mode-lex-analyzer--states) - - ;; Tokens - (should (equal phps-mode-lex-analyzer--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-lex-analyzer--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-lex-analyzer--tokens) - ;; (message "States: %s" phps-mode-lex-analyzer--states) - (should (equal phps-mode-lex-analyzer--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-lex-analyzer--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) - - (phps-mode-lex-analyzer--process-changes) - - ;; Final state - ;; (message "Tokens %s" phps-mode-lex-analyzer--tokens) - ;; (message "States: %s" phps-mode-lex-analyzer--states) - (should (equal phps-mode-lex-analyzer--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-lex-analyzer--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-lex-analyzer--tokens) - ;; (message "Before States: %s" phps-mode-lex-analyzer--states) - - (should (equal phps-mode-lex-analyzer--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-lex-analyzer--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-lex-analyzer--process-changes) - - ;; (message "After Tokens %s" phps-mode-lex-analyzer--tokens) - ;; (message "After States: %s" phps-mode-lex-analyzer--states) - (should (equal phps-mode-lex-analyzer--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-lex-analyzer--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-lex-analyzer--get-imenu) '(("myFunctionA" . 16) ("myFunctionB" . 42)))) - - (goto-char 32) - (newline-and-indent) - - (phps-mode-lex-analyzer--process-changes) + (phps-mode-test--incremental-vs-intial-buffer + "<?php\n\nif (\n true\n && false\n) {\n echo 'My long string here';\n if (\nfalse\n || true\n ) {\n echo 'Two lines of'\n . 'strings here';\n }\n}" + "Integration-test 15 white-space changes to see if nesting is maintained." + (goto-char 80) + (execute-kbd-macro (kbd "<tab>"))) - (should (equal (phps-mode-lex-analyzer--get-imenu) '(("myFunctionA" . 16) ("myFunctionB" . 43))))) + (phps-mode-test--incremental-vs-intial-buffer + "<?php\n\nif (\n true\n && false\n) {\n echo 'My long string here';\n if (\nfalse\n || true\n ) {\n echo 'Two lines of'\n . 'strings here';\n }\n}" + "Integration-test 16 white-space changes to see if nesting is maintained." + (goto-char 80) + (execute-kbd-macro (kbd "<tab>")) + (goto-char 117) + (execute-kbd-macro (kbd "<return>"))) ) (defun phps-mode-test-integration () "Run test for integration." ;; (setq debug-on-error t) - ;; (setq phps-mode-analyzer--process-on-indent-and-imenu t) (phps-mode-test-integration--incremental-vs-initial-buffers) - ;; (phps-mode-test-integration--whitespace-modifications) ) (phps-mode-test-integration) diff --git a/test/phps-mode-test-lexer.el b/test/phps-mode-test-lexer.el index 8c6b635..2254bdc 100644 --- a/test/phps-mode-test-lexer.el +++ b/test/phps-mode-test-lexer.el @@ -604,53 +604,53 @@ (should (equal - '((68 76 1 '(1)) - (10 67 1 '(1)) - (1 9 1 '(1))) + '((68 76 1 '(1) nil nil nil) + (10 67 1 '(1) nil nil nil) + (1 9 1 '(1) nil nil nil)) (phps-mode-lex-analyzer--get-moved-states - '((66 74 1 '(1)) - (8 65 1 '(1)) - (1 7 1 '(1))) + '((66 74 1 '(1) nil nil nil) + (8 65 1 '(1) nil nil nil) + (1 7 1 '(1) nil nil nil)) 6 2))) (should (equal - '((67 75 1 '(1)) - (9 66 1 '(1)) - (2 8 1 '(1))) + '((67 75 1 '(1) nil nil nil) + (9 66 1 '(1) nil nil nil) + (2 8 1 '(1) nil nil nil)) (phps-mode-lex-analyzer--get-moved-states - '((66 74 1 '(1)) - (8 65 1 '(1)) - (1 7 1 '(1))) + '((66 74 1 '(1) nil nil nil) + (8 65 1 '(1) nil nil nil) + (1 7 1 '(1) nil nil nil)) 0 1))) (should (equal - '((66 74 1 '(1)) - (8 65 1 '(1)) - (1 7 1 '(1))) + '((66 74 1 '(1) nil nil nil) + (8 65 1 '(1) nil nil nil) + (1 7 1 '(1) nil nil nil)) (phps-mode-lex-analyzer--get-moved-states - '((66 74 1 '(1)) - (8 65 1 '(1)) - (1 7 1 '(1))) + '((66 74 1 '(1) nil nil nil) + (8 65 1 '(1) nil nil nil) + (1 7 1 '(1) nil nil nil)) 100 1))) (should (equal - '((64 72 1 '(1)) - (6 63 1 '(1)) - (1 7 1 '(1))) + '((64 72 1 '(1) nil nil nil) + (6 63 1 '(1) nil nil nil) + (1 7 1 '(1) nil nil nil)) (phps-mode-lex-analyzer--get-moved-states - '((66 74 1 '(1)) - (8 65 1 '(1)) - (3 9 1 '(1))) + '((66 74 1 '(1) nil nil nil) + (8 65 1 '(1) nil nil nil) + (3 9 1 '(1) nil nil nil)) 3 -2))))