branch: externals/parser-generator commit dcbbdeedc892d27cb510eb4b3f821e18a00cb8f6 Author: Christian Johansson <christ...@cvj.se> Commit: Christian Johansson <christ...@cvj.se>
Started on support for symbol attributes --- parser-generator.el | 96 ++++++++++++++++++++++++++++++++++++------- test/parser-generator-test.el | 94 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 163 insertions(+), 27 deletions(-) diff --git a/parser-generator.el b/parser-generator.el index a11d9e4..e662c87 100644 --- a/parser-generator.el +++ b/parser-generator.el @@ -10,63 +10,88 @@ ;;; Variables: -(defvar parser-generator--debug +(defvar + parser-generator--attributes + nil + "List of valid attributes.") + +(defvar + parser-generator--debug nil "Whether to print debug messages or not.") -(defvar parser-generator--e-identifier +(defvar + parser-generator--e-identifier 'e "The identifier used for ε-symbol. Default value 'e.") -(defvar parser-generator--eof-identifier +(defvar + parser-generator--eof-identifier '$ "The identifier used for end of file identifier. Default value is '$.") -(defvar parser-generator--grammar +(defvar + parser-generator--grammar nil "Current grammar used in parser.") -(defvar parser-generator--f-sets +(defvar + parser-generator--f-sets nil "Generated F-sets for grammar.") -(defvar parser-generator--f-free-sets +(defvar + parser-generator--f-free-sets nil "Generated e-free F-sets for grammar.") -(defvar parser-generator--look-ahead-number +(defvar + parser-generator--look-ahead-number nil "Current look-ahead number used.") -(defvar parser-generator--table-firsts +(defvar + parser-generator--table-firsts nil "Hash-table of calculated firsts for quicker parser generation.") -(defvar parser-generator--table-look-aheads-p +(defvar + parser-generator--table-attributes-p + nil + "Hash-table of attributes.") + +(defvar + parser-generator--table-look-aheads-p nil "Hash-table of look-aheads for quick checking.") -(defvar parser-generator--table-non-terminal-p +(defvar + parser-generator--table-non-terminal-p nil "Hash-table of terminals for quick checking.") -(defvar parser-generator--table-productions-rhs +(defvar + parser-generator--table-productions-rhs nil "Hash-table of productions RHS indexed by LHS for quick retrieving.") -(defvar parser-generator--table-productions-number +(defvar + parser-generator--table-productions-number nil "Hash-table indexed by production and value is production-number.") -(defvar parser-generator--table-productions-number-reverse +(defvar + parser-generator--table-productions-number-reverse nil "Hash-table indexed by production-number and value is production.") -(defvar parser-generator--table-terminal-p +(defvar + parser-generator--table-terminal-p nil "Hash-table of non-terminals for quick checking.") -(defvar parser-generator--table-translations +(defvar + parser-generator--table-translations nil "Hash-table indexed by production-number and value is translation function.") @@ -501,6 +526,15 @@ parser-generator--grammar) new-productions))) + (setq + parser-generator--table-attributes-p + (make-hash-table :test 'equal)) + (dolist (attribute parser-generator--attributes) + (puthash + attribute + t + parser-generator--table-attributes-p)) + (let ((look-aheads (parser-generator--get-grammar-look-aheads))) (setq @@ -585,6 +619,38 @@ (setq index (1+ index))) response)) +(defun parser-generator--valid-attribute-p (attribute) + "Check if ATTRIBUTE is valid." + (gethash + attribute + parser-generator--table-attributes-p)) + +(defun parser-generator--valid-attributes-p (attributes) + "Check if all ATTRIBUTES are valid." + (let ((is-valid t) + (length (length attributes)) + (index 0)) + (unless (listp attributes) + (setq is-valid nil)) + (while (and + is-valid + (< index length)) + (let ((element + (nth index attributes))) + (unless + (parser-generator--valid-attribute-p + element) + (message "'%S' is not valid in '%S' from '%S' index: '%S'" + element + parser-generator--table-attributes-p + attributes + index) + (setq + is-valid + nil))) + (setq index (+ index 2))) + is-valid)) + (defun parser-generator--valid-e-p (symbol) "Return whether SYMBOL is the e identifier or not." (eq symbol parser-generator--e-identifier)) diff --git a/test/parser-generator-test.el b/test/parser-generator-test.el index dfa9f73..1445fbe 100644 --- a/test/parser-generator-test.el +++ b/test/parser-generator-test.el @@ -480,6 +480,11 @@ (should (equal + t + (parser-generator--valid-grammar-p '((A B C) ("a" "b" "c") ((A ("a" (%prec 1)))) A)))) + + (should + (equal nil (parser-generator--valid-grammar-p '((A B C) ("a" "b" "c") ((A "a")) (A))))) @@ -573,7 +578,7 @@ (defun parser-generator-test--valid-sentential-form-p () "Test `parser-generator--valid-sentential-form-p'." - (message "Starting tests for (parser-generator--valid-sentential-form-p)") + (message "Starting tests for (parser-generator--valid-sentential-form-p)") (parser-generator-set-grammar '((S A B) ("a" "b") ((S A) (A ("b" "a")) (B ("b" (lambda(b) (message "Was here: %s" b))))) S)) (parser-generator-process-grammar) @@ -598,7 +603,7 @@ (defun parser-generator-test--valid-production-p () "Test `parser-generator--valid-production-p'." - (message "Starting tests for (parser-generator--valid-production-p)") + (message "Starting tests for (parser-generator--valid-production-p)") (should (equal t @@ -628,11 +633,11 @@ t (parser-generator--valid-production-p '(A (a (lambda(a) (message "Here 3 %s"))) b)))) - (message "Passed tests for (parser-generator--valid-production-p)")) + (message "Passed tests for (parser-generator--valid-production-p)")) (defun parser-generator-test--get-grammar-rhs () "Test `parser-generator--get-grammar-rhs'." - (message "Started tests for (parser-generator--get-grammar-rhs)") + (message "Started tests for (parser-generator--get-grammar-rhs)") (parser-generator-set-grammar '((S A B) ("a" "b") ((S A) (A ("b" "a")) (B ("b" (lambda(b) (message "Was here: %s" b))))) S)) @@ -667,13 +672,16 @@ (parser-generator-process-grammar) - (message "Passed tests for (parser-generator--get-grammar-rhs)")) + (message "Passed tests for (parser-generator--get-grammar-rhs)")) (defun parser-generator-test--valid-non-terminal-p () "Test `parser-generator--valid-non-terminal-p'." - (message "Starting tests for (parser-generator--valid-non-terminal-p)") + (message "Starting tests for (parser-generator--valid-non-terminal-p)") (parser-generator-set-grammar '((S A B) ("a" "b") ((S A) (S (B)) (B "a") (A "a") (A ("b" "a"))) S)) + (setq + parser-generator--attributes + '(%prec)) (parser-generator-process-grammar) (should @@ -683,6 +691,10 @@ (should (equal t + (parser-generator--valid-non-terminal-p '(S (%prec 1))))) + (should + (equal + t (parser-generator--valid-non-terminal-p 'A))) (should (equal @@ -697,13 +709,65 @@ nil (parser-generator--valid-non-terminal-p "a"))) - (message "Passed tests for (parser-generator--valid-non-terminal-p)")) + (message "Passed tests for (parser-generator--valid-non-terminal-p)")) + +(defun parser-generator-test--valid-attribute-p () + "Test `parser-generator--valid-attribute-p'." + (message "Starting tests for (parser-generator--valid-attribute-p)") + + (parser-generator-set-grammar '((S A B) ("a" "b") ((S A) (S (B)) (B "a") (A "a") (A ("b" "a"))) S)) + (setq + parser-generator--attributes + '(%abc depth length)) + (parser-generator-process-grammar) + + (parser-generator--valid-attribute-p + '%abc) + + (should + (equal + t + (parser-generator--valid-attribute-p + '%abc))) + (should + (equal + nil + (parser-generator--valid-attribute-p + '%prec))) + + (message "Passed tests for (parser-generator--valid-attribute-p)")) + +(defun parser-generator-test--valid-attributes-p () + "Test `parser-generator--valid-attributes-p'." + (message "Starting tests for (parser-generator--valid-attributes-p)") + + (parser-generator-set-grammar '((S A B) ("a" "b") ((S A) (S (B)) (B "a") (A "a") (A ("b" "a"))) S)) + (setq + parser-generator--attributes + '(%abc depth length)) + (parser-generator-process-grammar) + + (should + (equal + t + (parser-generator--valid-attributes-p + '(%abc 1 depth 0 length 3)))) + (should + (equal + nil + (parser-generator--valid-attributes-p + '(%prec 0)))) + + (message "Passed tests for (parser-generator--valid-attributes-p)")) (defun parser-generator-test--valid-terminal-p () "Test `parser-generator--valid-terminal-p'." - (message "Starting tests for (parser-generator--valid-terminal-p)") + (message "Starting tests for (parser-generator--valid-terminal-p)") (parser-generator-set-grammar '((S A B) ("a" "b") ((S A) (S (B)) (B "a") (A "a") (A ("b" "a"))) S)) + (setq + parser-generator--attributes + '(%prec)) (parser-generator-process-grammar) (should @@ -713,6 +777,10 @@ (should (equal t + (parser-generator--valid-terminal-p '("a" (%prec 1))))) + (should + (equal + t (parser-generator--valid-terminal-p "b"))) (should (equal @@ -727,11 +795,11 @@ nil (parser-generator--valid-terminal-p 'A))) - (message "Passed tests for (parser-generator--valid-terminal-p)")) + (message "Passed tests for (parser-generator--valid-terminal-p)")) (defun parser-generator-test--merge-max-terminals () "Test `parser-generator--merge-max-terminals'." - (message "Starting tests for (parser-generator--merge-max-terminals)") + (message "Starting tests for (parser-generator--merge-max-terminals)") (should (equal @@ -749,11 +817,11 @@ '(b e) 3))) - (message "Passed tests for (parser-generator--merge-max-terminals)")) + (message "Passed tests for (parser-generator--merge-max-terminals)")) (defun parser-generator-test--get-list-permutations () "Test `parser-generator--get-list-permutations'." - (message "Starting tests for (parser-generator--get-list-permutations)") + (message "Starting tests for (parser-generator--get-list-permutations)") (parser-generator-set-look-ahead-number 1) (parser-generator-set-grammar '((S A B) ("a" "b") ((S A) (S (B)) (B "a") (A "a") (A ("b" "a"))) S)) @@ -825,6 +893,8 @@ (parser-generator-test--get-list-permutations) (parser-generator-test--merge-max-terminals) (parser-generator-test--sort-list) + (parser-generator-test--valid-attribute-p) + (parser-generator-test--valid-attributes-p) (parser-generator-test--valid-grammar-p) (parser-generator-test--valid-look-ahead-number-p) (parser-generator-test--valid-look-ahead-p)