[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/parser-generator ccaf4b5 080/434: More stuff
From: |
ELPA Syncer |
Subject: |
[elpa] externals/parser-generator ccaf4b5 080/434: More stuff |
Date: |
Mon, 29 Nov 2021 15:59:13 -0500 (EST) |
branch: externals/parser-generator
commit ccaf4b58e98153642683a59b8c73976de261688d
Author: Christian Johansson <christian@cvj.se>
Commit: Christian Johansson <christian@cvj.se>
More stuff
---
parser.el | 205 ++++++++++++++++++++++++----------------------------
test/parser-test.el | 18 +----
2 files changed, 96 insertions(+), 127 deletions(-)
diff --git a/parser.el b/parser.el
index e13a305..7717d9a 100644
--- a/parser.el
+++ b/parser.el
@@ -652,81 +652,50 @@
(setq follow-set (parser--distinct follow-set)))
follow-set))
-;; TODO Don't check for distincts prefixes but LR-items
;; Algorithm 5.9, p. 389
(defun parser--lr-items-for-grammar ()
"Calculate set of valid LR(k) items for grammar."
- (let ((prefixes)
- (marked-prefixes (make-hash-table :test 'equal))
- (lr-items)
+ (let ((lr-items)
+ (unmarked-lr-items)
+ (marked-lr-items (make-hash-table :test 'equal))
(symbols (append (parser--get-grammar-non-terminals)
(parser--get-grammar-terminals))))
(let ((e-set (parser--lr-items-for-prefix parser--e-identifier)))
;;(1) Place V(e) in S. The set V(e) is initially unmarked.
- (setq lr-items (append lr-items e-set))
- (push `(,parser--e-identifier) prefixes))
+ (setq unmarked-lr-items (append unmarked-lr-items e-set)))
+ ;; (2) If a set of items a in S is unmarked
;; (3) Repeat step (2) until all sets of items in S are marked.
- (let ((prefix)
- (i-left 100))
+ (let ((lr-item))
+ (while unmarked-lr-items
- ;; (2) If a set of items a in S is unmarked
- (while (and
- prefixes
- (> i-left 0))
- (setq i-left (1- i-left))
-
- ;; (2) Mark a by computing for each X in N u E, GOTO (a, X).
(Algorithm 5.8 can be used here.)
- (setq prefix (pop prefixes))
-
- ;; e-identifier is converted to nil prefix
- (when (and
- (= (length prefix) 1)
- (parser--valid-e-p (car prefix)))
- (setq prefix nil))
+ ;; (2) Mark a
+ (setq lr-item (pop unmarked-lr-items))
+ (puthash lr-item t marked-lr-items)
+ (setq lr-items (append lr-items lr-item))
- ;; (message "prefix: %s" prefix)
-
- (puthash prefix t marked-prefixes)
+ (message "lr-item: %s" lr-item)
+ ;; (2) By computing for each X in N u E, GOTO (a, X). (Algorithm 5.8
can be used here.)
;; V(X1,...,Xi) = GOTO(V(X1,...,Xi-1), Xi)
(dolist (symbol symbols)
- (let ((alternative-prefix (append prefix (list symbol))))
- ;; (message "alternative-prefix: %s" alternative-prefix)
+ (message "symbol: %s" symbol)
- ;; and is not already in S
- (unless (gethash alternative-prefix marked-prefixes)
- (let ((prefix-lr-items (parser--lr-items-for-prefix
alternative-prefix)))
+ (let ((prefix-lr-items (parser--lr-items-for-goto (list lr-item)
symbol)))
- (message "V%s = %s" alternative-prefix prefix-lr-items)
+ (message "GOTO(%s, %s) = %s" lr-item symbol prefix-lr-items)
+ ;; If a' = GOTO(a, X) is nonempty
+ (when prefix-lr-items
+ (dolist (prefix-lr-item prefix-lr-items)
-
- (when prefix-lr-items
+ ;; and is not already in S
+ (unless (gethash prefix-lr-item marked-lr-items)
;; Note that GOTO(a, X) will always be empty if all items in
a
;; have the dot at the right end of the production
- (let ((dot-at-right-end t)
- (production-i 0)
- (production-length (length prefix-lr-items)))
- (while (and
- (< production-i production-length)
- dot-at-right-end)
- (let ((production-item (nth production-i
prefix-lr-items)))
-
- ;; When suffix is not nil dot is at the right end
- (when (nth 2 production-item)
- (setq dot-at-right-end nil)))
-
- (setq production-i (1+ production-i)))
-
- (unless dot-at-right-end
- ;; If a' = GOTO(a, X) is nonempty
- (message "viable-prefix: %s" alternative-prefix)
-
- ;; then add a' to S as an unmarked set of items
- (push alternative-prefix prefixes)
- (setq lr-items (append lr-items
prefix-lr-items)))))))))))
+ ;; then add a' to S as an unmarked set of items
+ (push unmarked-lr-items prefix-lr-item))))))))
lr-items))
@@ -816,6 +785,7 @@
;; (c) Repeat (b) until no more items can
be added to V(e)
(setq found-new t))))))))))))))
+
(parser--debug
(message "V(e) = %s" lr-items-e))
@@ -838,68 +808,14 @@
(if (gethash prefix-acc parser--table-lr-items-for-prefix)
(setq prefix-previous (gethash prefix-acc
parser--table-lr-items-for-prefix))
+ (setq lr-new-item (parser--lr-items-for-goto prefix-previous
prefix))
+
(parser--debug
(message "prefix: %s" prefix)
(message "prefix-acc: %s" prefix-acc)
- (message "prefix-previous: %s" prefix-previous))
-
- (dolist (lr-item prefix-previous)
- (let ((lr-item-lhs (nth 0 lr-item))
- (lr-item-prefix (nth 1 lr-item))
- (lr-item-suffix (nth 2 lr-item))
- (lr-item-look-ahead (nth 3 lr-item)))
- (let ((lr-item-suffix-first (car lr-item-suffix))
- (lr-item-suffix-rest (cdr lr-item-suffix)))
+ (message "prefix-previous: %s" prefix-previous)
+ (message "lr-new-item: %s" lr-new-item))
- ;; (a) If [A -> a . XiB, u] is in V(X1,...,Xi-1)
- (when (eq lr-item-suffix-first prefix)
-
- ;; Add [A -> aXi . B, u] to V(X1,...,Xi)
- (let ((combined-prefix (append lr-item-prefix (list
prefix))))
- (parser--debug
- (message "lr-new-item-1: %s" `(,lr-item-lhs
,combined-prefix ,lr-item-suffix-rest ,lr-item-look-ahead)))
- (push `(,lr-item-lhs ,combined-prefix
,lr-item-suffix-rest ,lr-item-look-ahead) lr-new-item))))))
-
- ;; (c) Repeat step (2b) until no more new items can be added
to V(X1,...,Xi)
- (let ((added-new t))
- (while added-new
- (setq added-new nil)
- (dolist (lr-item lr-new-item)
- (let ((lr-item-suffix (nth 2 lr-item)))
- (let ((lr-item-suffix-first (car lr-item-suffix))
- (lr-item-suffix-rest (cdr lr-item-suffix)))
-
- ;; (b) If [A -> a . Bb, u] has been placed in
V(X1,...,Xi)
- ;; and B -> D is in P
- (when (parser--valid-non-terminal-p
lr-item-suffix-first)
-
- (let ((lr-item-suffix-rest-first (parser--first
lr-item-suffix-rest)))
- (unless lr-item-suffix-rest-first
- (setq lr-item-suffix-rest-first (list nil)))
- (let ((sub-production (parser--get-grammar-rhs
lr-item-suffix-first)))
-
- ;; For each production with B as LHS
- (dolist (sub-rhs sub-production)
-
- ;; Transform e-productions into nil
- (when (and
- (= (length sub-rhs) 1)
- (parser--valid-e-p (car sub-rhs)))
- (setq sub-rhs nil))
-
- ;; For each x in FIRST(αu)
- (dolist (f lr-item-suffix-rest-first)
-
- ;; then add [B -> . D, x] to
V(X1,...,Xi) for each x in FIRST(bu)
- ;; provided it is not already there
- (unless (gethash `(,prefix-acc
,lr-item-suffix-first nil ,sub-rhs ,f) lr-item-exists)
- (setq added-new t)
- (parser--debug
- (message "lr-new-item-2: %s"
`(,lr-item-suffix-first nil ,sub-rhs ,f)))
- (puthash `(,prefix-acc
,lr-item-suffix-first nil ,sub-rhs ,f) t lr-item-exists)
- (push `(,lr-item-suffix-first nil
,sub-rhs ,f) lr-new-item))))))))))))
-
- (setq lr-new-item (sort lr-new-item 'parser--sort-list))
(setq prefix-previous lr-new-item)
(parser--debug
(message "V%s = %s" prefix-acc lr-new-item))
@@ -909,6 +825,71 @@
(message "γ: %s" γ))
(gethash γ parser--table-lr-items-for-prefix))))
+(defun parser--lr-items-for-goto (previous-lr-item x)
+ "Calculate LR-items for GOTO(PREVIOUS-LR-ITEM, X)."
+ (let ((lr-new-item)
+ (lr-item-exists (make-hash-table :test 'equal)))
+ (parser--debug (message "x: %s" x))
+
+ (dolist (lr-item previous-lr-item)
+ (let ((lr-item-lhs (nth 0 lr-item))
+ (lr-item-prefix (nth 1 lr-item))
+ (lr-item-suffix (nth 2 lr-item))
+ (lr-item-look-ahead (nth 3 lr-item)))
+ (let ((lr-item-suffix-first (car lr-item-suffix))
+ (lr-item-suffix-rest (cdr lr-item-suffix)))
+
+ ;; (a) If [A -> a . XiB, u] is in V(X1,...,Xi-1)
+ (when (eq lr-item-suffix-first x)
+
+ ;; Add [A -> aXi . B, u] to V(X1,...,Xi)
+ (let ((combined-prefix (append lr-item-prefix (list x))))
+ (parser--debug
+ (message "lr-new-item-1: %s" `(,lr-item-lhs ,combined-prefix
,lr-item-suffix-rest ,lr-item-look-ahead)))
+ (push `(,lr-item-lhs ,combined-prefix ,lr-item-suffix-rest
,lr-item-look-ahead) lr-new-item))))))
+
+ ;; (c) Repeat step (2b) until no more new items can be added to
V(X1,...,Xi)
+ (let ((added-new t))
+ (while added-new
+ (setq added-new nil)
+ (dolist (lr-item lr-new-item)
+ (let ((lr-item-suffix (nth 2 lr-item)))
+ (let ((lr-item-suffix-first (car lr-item-suffix))
+ (lr-item-suffix-rest (cdr lr-item-suffix)))
+
+ ;; (b) If [A -> a . Bb, u] has been placed in V(X1,...,Xi)
+ ;; and B -> D is in P
+ (when (parser--valid-non-terminal-p lr-item-suffix-first)
+
+ (let ((lr-item-suffix-rest-first (parser--first
lr-item-suffix-rest)))
+ (unless lr-item-suffix-rest-first
+ (setq lr-item-suffix-rest-first (list nil)))
+ (let ((sub-production (parser--get-grammar-rhs
lr-item-suffix-first)))
+
+ ;; For each production with B as LHS
+ (dolist (sub-rhs sub-production)
+
+ ;; Transform e-productions into nil
+ (when (and
+ (= (length sub-rhs) 1)
+ (parser--valid-e-p (car sub-rhs)))
+ (setq sub-rhs nil))
+
+ ;; For each x in FIRST(αu)
+ (dolist (f lr-item-suffix-rest-first)
+
+ ;; then add [B -> . D, x] to V(X1,...,Xi) for each x
in FIRST(bu)
+ ;; provided it is not already there
+ (let ((lr-item-to-add `(,lr-item-suffix-first nil
,sub-rhs ,f)))
+ (unless (gethash lr-item-to-add lr-item-exists)
+ (setq added-new t)
+ (parser--debug (message "lr-item-to-add: %s"
lr-item-to-add))
+ (puthash lr-item-to-add t lr-item-exists)
+ (push lr-item-to-add lr-new-item)))))))))))))
+
+ (setq lr-new-item (sort lr-new-item 'parser--sort-list))
+ lr-new-item))
+
(provide 'parser)
diff --git a/test/parser-test.el b/test/parser-test.el
index caed787..90aca30 100644
--- a/test/parser-test.el
+++ b/test/parser-test.el
@@ -231,6 +231,8 @@
(parser--set-grammar '((Sp S) (a b) ((Sp S) (S (S a S b)) (S e)) Sp))
(parser--set-look-ahead-number 1)
+ (message "LR-items for grammar: %s" (parser--lr-items-for-grammar))
+
(should
(equal
'((S nil (S a S b) (a))
@@ -326,19 +328,6 @@
(parser--lr-items-for-prefix '(S a b))))
(message "Passed V(Sab)")
- ;; a4 p. 390
- (should
- (equal
- '((S (S a) (S b) (a))
- (S (S a) (S b) (e))
- (S nil (S a S b) (a))
- (S nil (S a S b) (b))
- (S nil nil (a))
- (S nil nil (e)))
- (parser--lr-items-for-prefix '(S a S b))))
- (message "Passed V(SaSb)")
-
-
(message "Passed tests for (parser--lr-items-for-prefix)"))
(defun parser-test--valid-grammar-p ()
@@ -477,8 +466,7 @@
(parser-test--e-free-first)
(parser-test--follow)
(parser-test--lr-items-for-prefix)
- ;; (parser-test--lr-items-for-grammar)
- )
+ (parser-test--lr-items-for-grammar))
(provide 'parser-test)
- [elpa] externals/parser-generator 59aea4d 077/434: More tweaking new algorithm, (continued)
- [elpa] externals/parser-generator 59aea4d 077/434: More tweaking new algorithm, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator d0c9663 082/434: Passing test for distinct LR-items for grammar, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 7a48197 084/434: Removed obsolete variable, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 7fe7318 087/434: Passed test for distinct LR-items for grammar, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator ba95bff 094/434: Started on new algorithm, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 6f524ed 108/434: Various stuff, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 79c06fd 113/434: Added error signal if no parser action or LR-item set is found, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator daf93e0 097/434: Added failing unit test for action tables generation, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 32263b7 074/434: Added cache to function which calculates LR-items for prefix, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 21164b6 064/434: Added documentation for (lr-items), ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator ccaf4b5 080/434: More stuff,
ELPA Syncer <=
- [elpa] externals/parser-generator bdbedf4 078/434: Suffixes in LR-items that only contain e-identifier are now set as nil, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 0e075d7 081/434: Fixed issue with algorithm 5.9, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator fe6037b 088/434: Generating valid GOTO-table, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator d5284b5 091/434: Added algorithm 5.10, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 0304b78 092/434: Added a unit-test to invalidate LR-items, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 69bfe16 006/434: Removed white-space, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 1613e2e 096/434: Byte-compilation and unit tests working after refactor, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 31c7ba7 098/434: Work on function that generates all possible look-aheads, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 53980d4 102/434: More documentation, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 882d725 105/434: Added TODO item, ELPA Syncer, 2021/11/29