[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/parser-generator 221446d647 24/82: Started implementati
From: |
Christian Johansson |
Subject: |
[elpa] externals/parser-generator 221446d647 24/82: Started implementation of LLk validation |
Date: |
Thu, 12 May 2022 13:28:14 -0400 (EDT) |
branch: externals/parser-generator
commit 221446d647a56c08c638fd7f5ca18f8835a4a98d
Author: Christian Johansson <christian@cvj.se>
Commit: Christian Johansson <christian@cvj.se>
Started implementation of LLk validation
---
parser-generator-ll.el | 88 ++++++++++++++++++++++++++++++++++++++--
parser-generator.el | 4 +-
test/parser-generator-ll-test.el | 52 ++++++++++++++++++++----
3 files changed, 133 insertions(+), 11 deletions(-)
diff --git a/parser-generator-ll.el b/parser-generator-ll.el
index 96d0493ada..035c5d8508 100644
--- a/parser-generator-ll.el
+++ b/parser-generator-ll.el
@@ -334,11 +334,93 @@
parsing-table))
-;; TODO
;; Algorithm 5.4 p. 357
(defun parser-generator-ll--valid-grammar-p ()
- "Test for LL(k)-ness. Output t if grammar G is LL(k). nil otherwise."
- )
+ "Test for LL(k)-ness. Output t if grammar is LL(k). nil otherwise."
+ (let ((stack)
+ (stack-item)
+ (k (max 1 parser-generator--look-ahead-number))
+ (distinct-production-p (make-hash-table :test 'equal))
+ (valid t))
+
+ ;; (1) Construct T_0, the LL(k) table associated with S {e}
+ (let* ((start (parser-generator--get-grammar-start))
+ (start-rhss (parser-generator--get-grammar-rhs start)))
+ (dolist (start-rhs start-rhss)
+ (let* ((production (list (list start) start-rhs)))
+ (push
+ production
+ stack)
+ (puthash
+ production
+ t
+ distinct-production-p))))
+ (setq stack (nreverse stack))
+ (parser-generator--debug
+ (message "stack: %S" stack))
+
+ (while (and
+ stack
+ valid)
+ (setq stack-item (pop stack))
+ (let ((production-lhs
+ (nth 0 stack-item))
+ (production-rhs
+ (nth 1 stack-item)))
+
+ ;; For each non-terminal in the production right-hand side
+ ;; push a new item to stack with a local-follow
+ ;; and a new left-hand-side
+ (let ((sub-symbol-index 0)
+ (sub-symbol-length (length production-rhs)))
+ (while (< sub-symbol-index sub-symbol-length)
+ (let ((sub-symbol (nth sub-symbol-index production-rhs)))
+ (when (parser-generator--valid-non-terminal-p
+ sub-symbol)
+ (let* ((local-follow
+ (nthcdr (1+ sub-symbol-index) production-rhs))
+ (first-local-follow-sets
+ (parser-generator--first local-follow nil t t))
+ (sub-symbol-rhss
+ (parser-generator--get-grammar-rhs sub-symbol))
+ (first-sub-symbol-rhss-sets
+ (parser-generator--first sub-symbol-rhss nil t t))
+ (merged-terminal-sets
+ (parser-generator--merge-max-terminal-sets
+ first-local-follow-sets
+ first-sub-symbol-rhss-sets))
+ (distinct-item-p
+ (make-hash-table :test 'equal)))
+ (dolist (merged-terminal-set merged-terminal-sets)
+ (if (gethash
+ merged-terminal-set
+ distinct-item-p)
+ (progn
+ (setq valid nil)
+ (message "merged-terminal-set: %S was not distinct"
merged-terminal-set))
+ (puthash
+ merged-terminal-set
+ t
+ distinct-item-p)))
+ (let ((production
+ (list
+ (list sub-symbol)
+ sub-symbol-rhss)))
+ (unless
+ (gethash
+ production
+ distinct-production-p)
+ (push
+ production
+ stack)
+ (puthash
+ production
+ t
+ distinct-production-p))))))
+ (setq
+ sub-symbol-index
+ (1+ sub-symbol-index))))))
+ valid))
(provide 'parser-generator-ll)
diff --git a/parser-generator.el b/parser-generator.el
index 76847aca49..d995fcbf7d 100644
--- a/parser-generator.el
+++ b/parser-generator.el
@@ -1793,7 +1793,9 @@
(setq
expanded-lists-index
(1+ expanded-lists-index)))
- (when (>= minimum-terminal-count k)
+ (when (and
+ minimum-terminal-count
+ (>= minimum-terminal-count k))
(setq still-looking nil)
(parser-generator--debug
(message
diff --git a/test/parser-generator-ll-test.el b/test/parser-generator-ll-test.el
index 37c84fa6cb..5648fc0104 100644
--- a/test/parser-generator-ll-test.el
+++ b/test/parser-generator-ll-test.el
@@ -158,22 +158,60 @@
"Test `parser-generator-ll--valid-grammar-p'."
(message "Started tests for (parser-generator-ll--valid-grammar-p)")
+ ;; Example 5.14 p. 350
+ ;; Example 5.15 p. 351
+ (parser-generator-set-e-identifier 'e)
+ (parser-generator-set-look-ahead-number 2)
+ (parser-generator-set-grammar
+ '(
+ (S A)
+ (a b)
+ (
+ (S (a A a a) (b A b a))
+ (A b e)
+ )
+ S
+ )
+ )
+ (parser-generator-process-grammar)
+ (parser-generator-ll--valid-grammar-p)
+ (should
+ (equal
+ (parser-generator-ll--valid-grammar-p)
+ t))
+ (message "Passed first valid test")
- (message "Passed tests for (parser-generator-ll--valid-grammar-p)"))
+ ;; Example 5.14 p. 350
+ ;; Example 5.15 p. 351
+ (parser-generator-set-e-identifier 'e)
+ (parser-generator-set-look-ahead-number 2)
+ (parser-generator-set-grammar
+ '(
+ (S A)
+ (a b)
+ (
+ (S (a A a a) (b A b a))
+ (A b e a)
+ )
+ S
+ )
+ )
+ (parser-generator-process-grammar)
+ (should
+ (equal
+ (parser-generator-ll--valid-grammar-p)
+ nil))
+ (message "Passed second valid test")
-(defun parser-generator-ll-test-generate-parser-tables ()
- "Test `parser-generator-ll-generate-parser-tables'."
- (message "Started tests for (parser-generator-ll-generate-parser-tables)")
+ (message "Passed tests for (parser-generator-ll--valid-grammar-p)"))
- (message "Passed tests for (parser-generator-ll-generate-parser-tables)"))
(defun parser-generator-ll-test ()
"Run test."
(parser-generator-ll-test--generate-tables)
(parser-generator-ll-test--generate-parsing-table)
- (parser-generator-ll-test--valid-grammar-p)
- (parser-generator-ll-test-generate-parser-tables))
+ (parser-generator-ll-test--valid-grammar-p))
(provide 'parser-generator-ll-test)
- [elpa] externals/parser-generator d397a1d48e 12/82: Improved variable naming, (continued)
- [elpa] externals/parser-generator d397a1d48e 12/82: Improved variable naming, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator b09b22c0be 13/82: Passing test for LL(k) table Example 5.15, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 7c10be74b8 06/82: Added TODO items, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 1d1e4e4bf8 03/82: More work on LL(k) parser, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 4cb0a0b941 08/82: More work on LL table generation, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 29bad0440f 09/82: More work on LL table generation, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 87435188dd 15/82: Added function to set EOF-identifier, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator bab123bdda 17/82: Added reference to PHP 8.1, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator a2a629c16d 18/82: More work on data structure for LL-tables, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 542a50d9c1 20/82: Remove usage of a hash-table, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 221446d647 24/82: Started implementation of LLk validation,
Christian Johansson <=
- [elpa] externals/parser-generator ab4ce4d668 25/82: Tests for validating LLk grammar passing, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 04eb4d066c 27/82: Started on test for Example 5.17, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 5c0bcd5f9a 36/82: Passing test for LL-table generation example 5.17, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 1290048b84 39/82: Improved documentation, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 57c6fdda2f 43/82: Passing test for generating LL-parser hash-table, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator b37ba1eddf 52/82: Created TODO item, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator af3740c46a 59/82: More refactoring, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 3d373f4dfa 60/82: Updated docs, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 020969094c 61/82: More refactoring, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 08ed55d35a 62/82: More work on k=1, Christian Johansson, 2022/05/12