[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/parser-generator 8e3084b 270/434: More work LRk parser
From: |
ELPA Syncer |
Subject: |
[elpa] externals/parser-generator 8e3084b 270/434: More work LRk parser k = 0 |
Date: |
Mon, 29 Nov 2021 15:59:55 -0500 (EST) |
branch: externals/parser-generator
commit 8e3084b739e3a2880b4db28f7c192f875f166c5f
Author: Christian Johansson <christian@cvj.se>
Commit: Christian Johansson <christian@cvj.se>
More work LRk parser k = 0
---
parser-generator-lr.el | 146 +++++++++++++++++++++++++++------------
parser-generator.el | 19 ++++-
test/parser-generator-lr-test.el | 21 +++---
3 files changed, 129 insertions(+), 57 deletions(-)
diff --git a/parser-generator-lr.el b/parser-generator-lr.el
index 3bc322f..64ae584 100644
--- a/parser-generator-lr.el
+++ b/parser-generator-lr.el
@@ -221,6 +221,8 @@
;; Algorithm 5.9, p. 389
(defun parser-generator-lr--generate-goto-tables ()
"Calculate set of valid LR(k) items for grammar and a GOTO-table."
+ (parser-generator--debug
+ (message "(parser-generator-lr--generate-goto-tables)"))
(let ((lr-item-set-new-index 0)
(goto-table)
(unmarked-lr-item-sets)
@@ -240,7 +242,12 @@
unmarked-lr-item-sets)
(setq
lr-item-set-new-index
- (1+ lr-item-set-new-index)))
+ (1+ lr-item-set-new-index))
+ ;; Mark the initial set
+ (puthash
+ e-set
+ lr-item-set-new-index
+ marked-lr-item-sets))
;; (2) If a set of items a in S is unmarked
;; (3) Repeat step (2) until all sets of items in S are marked.
@@ -255,15 +262,9 @@
(setq lr-items (car (cdr popped-item)))
(parser-generator--debug
(message "lr-item-set-index: %s" lr-item-set-index)
- (message "lr-items: %s" lr-items)
+ (message "marked lr-items: %s" lr-items)
(message "popped-item: %s" popped-item))
- ;; (2) Mark a
- (puthash
- lr-items
- lr-item-set-index
- marked-lr-item-sets)
-
(puthash
lr-item-set-index
lr-items
@@ -338,13 +339,18 @@
(if goto
(progn
(parser-generator--debug
- (message "Set already exists in: %s" goto))
+ (message
+ "Set already exists in: %s set: %s"
+ goto
+ prefix-lr-items))
(push
`(,symbol ,goto)
goto-table-table))
(parser-generator--debug
- (message "Set is new"))
+ (message
+ "Set is new: %s"
+ prefix-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
@@ -356,6 +362,11 @@
(push
`(,lr-item-set-new-index ,prefix-lr-items)
unmarked-lr-item-sets)
+ ;; (2) Mark a
+ (puthash
+ prefix-lr-items
+ lr-item-set-new-index
+ marked-lr-item-sets)
(setq
lr-item-set-new-index
(1+ lr-item-set-new-index))))))))
@@ -366,7 +377,9 @@
goto-table-table
'parser-generator--sort-list))
(push
- `(,lr-item-set-index ,goto-table-table)
+ `(
+ ,lr-item-set-index
+ ,goto-table-table)
goto-table)))
(setq
@@ -507,13 +520,23 @@
;; (a)
(dolist (rhs start-productions)
;; Add [S -> . α] to V(e)
- (push
- `(,(list start) nil ,rhs ,eof-list)
- lr-items-e)
- (puthash
- `(,e-list ,(list start) nil ,rhs ,eof-list)
- t
- lr-item-exists))
+ (if (= parser-generator--look-ahead-number 0)
+ ;; A dot-look-ahead is only used for k >= 1
+ (progn
+ (push
+ `(,(list start) nil ,rhs)
+ lr-items-e)
+ (puthash
+ `(,e-list ,(list start) nil ,rhs)
+ t
+ lr-item-exists))
+ (push
+ `(,(list start) nil ,rhs ,eof-list)
+ lr-items-e)
+ (puthash
+ `(,e-list ,(list start) nil ,rhs ,eof-list)
+ t
+ lr-item-exists)))
;; (b) Iterate every item in v-set(e), if [A -> . Bα, u] is an item
and B -> β is in P
;; then for each x in FIRST(αu) add [B -> . β, x] to v-set(e),
provided it is not already there
@@ -573,20 +596,38 @@
(message "f: %s" f))
;; Add [B -> . β, x] to V(e), provided it is
not already there
- (unless
- (gethash
+ (if (= parser-generator--look-ahead-number 0)
+
+ ;; A dot look-ahead is only used for k
>= 1
+ (unless
+ (gethash
+ `(,e-list ,(list rhs-first) nil
,sub-rhs)
+ lr-item-exists)
+ (puthash
+ `(,e-list ,(list rhs-first) nil
,sub-rhs)
+ t
+ lr-item-exists)
+ (push
+ `(,(list rhs-first) nil ,sub-rhs)
+ lr-items-e)
+
+ ;; (c) Repeat (b) until no more items
can be added to V(e)
+ (setq found-new t))
+
+ (unless
+ (gethash
+ `(,e-list ,(list rhs-first) nil
,sub-rhs ,f)
+ lr-item-exists)
+ (puthash
`(,e-list ,(list rhs-first) nil
,sub-rhs ,f)
+ t
lr-item-exists)
- (puthash
- `(,e-list ,(list rhs-first) nil ,sub-rhs
,f)
- t
- lr-item-exists)
- (push
- `(,(list rhs-first) nil ,sub-rhs ,f)
- lr-items-e)
-
- ;; (c) Repeat (b) until no more items can
be added to V(e)
- (setq found-new t)))))))
+ (push
+ `(,(list rhs-first) nil ,sub-rhs ,f)
+ lr-items-e)
+
+ ;; (c) Repeat (b) until no more items
can be added to V(e)
+ (setq found-new t))))))))
(parser-generator--debug
(message "is not non-terminal")))))))))
@@ -680,19 +721,28 @@
(append
lr-item-prefix
(list x))))
- (parser-generator--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)))))
+ (let ((lr-new-item-1))
+ (if (= parser-generator--look-ahead-number 0)
+ ;; Only k >= 1 needs dot look-ahead
+ (progn
+ (setq
+ lr-new-item-1
+ `(,lr-item-lhs
+ ,combined-prefix
+ ,lr-item-suffix-rest)))
+ (setq
+ lr-new-item-1
+ `(,lr-item-lhs
+ ,combined-prefix
+ ,lr-item-suffix-rest
+ ,lr-item-look-ahead)))
+ (parser-generator--debug
+ (message
+ "lr-new-item-1: %s"
+ lr-new-item-1))
+ (push
+ lr-new-item-1
+ lr-new-item))))))
;; (c) Repeat step (2b) until no more new items can be added to
V(X1,...,Xi)
(when lr-new-item
@@ -759,6 +809,12 @@
;; provided it is not already there
(let ((lr-item-to-add
`(,(list lr-item-suffix-first) nil ,sub-rhs
,f)))
+ ;; Only k >= 1 needs dot a look-ahead
+ (when
+ (= parser-generator--look-ahead-number 0)
+ (setq
+ lr-item-to-add
+ `(,(list lr-item-suffix-first) nil ,sub-rhs)))
(unless
(gethash
lr-item-to-add
@@ -777,7 +833,9 @@
lr-new-item)))))))))))))
(setq
lr-new-item
- (sort lr-new-item 'parser-generator--sort-list)))
+ (sort
+ lr-new-item
+ 'parser-generator--sort-list)))
lr-new-item))
diff --git a/parser-generator.el b/parser-generator.el
index f0caf27..9cde3a5 100644
--- a/parser-generator.el
+++ b/parser-generator.el
@@ -11,7 +11,7 @@
(defvar parser-generator--debug
- nil
+ t
"Whether to print debug messages or not.")
(defvar parser-generator--e-identifier
@@ -417,9 +417,10 @@
(or
(parser-generator--valid-terminal-p sub-rhs-element)
(parser-generator--valid-non-terminal-p
sub-rhs-element)
- (parser-generator--valid-e-p sub-rhs-element))
+ (parser-generator--valid-e-p sub-rhs-element)
+ (parser-generator--valid-eof-p sub-rhs-element))
(error
- "Element %s in RHS %s of production %s is not a valid
terminal, non-terminal or e-identifier!"
+ "Element %s in RHS %s of production %s is not a valid
terminal, non-terminal, e-identifier or EOF-identifier!"
sub-rhs-element
rhs-element
lhs))
@@ -508,6 +509,18 @@
(defun parser-generator-process-grammar ()
"Process grammar."
(parser-generator--clear-cache)
+ (unless parser-generator--look-ahead-number
+ (error "No look-ahead-number defined!"))
+ (unless
+ (parser-generator--valid-look-ahead-number-p
+ parser-generator--look-ahead-number)
+ (error "Invalid look-ahead number k!"))
+ (unless parser-generator--grammar
+ (error "No grammar defined!"))
+ (unless
+ (parser-generator--valid-grammar-p
+ parser-generator--grammar)
+ (error "Invalid grammar G!"))
(parser-generator--load-symbols))
(defun parser-generator--sort-list (a b)
diff --git a/test/parser-generator-lr-test.el b/test/parser-generator-lr-test.el
index 573297c..cb37024 100644
--- a/test/parser-generator-lr-test.el
+++ b/test/parser-generator-lr-test.el
@@ -731,7 +731,7 @@
;; (5) B → 1
(parser-generator-set-grammar
- '((S E B) ("*" "+" "0" "1") ((S E) (E (E "*" B) (E "+" B) (B)) (B ("0")
("1"))) S))
+ '((S E B) ("*" "+" "0" "1") ((S (E $)) (E (E "*" B) (E "+" B) (B)) (B ("0")
("1"))) S))
(parser-generator-set-look-ahead-number 0)
(parser-generator-process-grammar)
@@ -783,29 +783,30 @@
(should
(equal
'((0 (
- ((S) nil (E $))
- ((E) nil (E "*" B))
- ((E) nil (E "+" B))
- ((E) nil (B))
((B) nil ("0"))
((B) nil ("1"))
+ ((E) nil (B))
+ ((E) nil (E "+" B))
+ ((E) nil (E "*" B))
+ ((S) nil (E $))
))
(1 (((B) ("0") nil)))
(2 (((B) ("1") nil)))
(3 (
- ((S) (E) ($))
- ((E) (E) ("*" B))
((E) (E) ("+" B))
+ ((E) (E) ("*" B))
+ ((S) (E) ($))
))
(4 (((E) (B) nil)))
(5 (
- ((E) (E "*") (B))
+ ((B) nil ("0"))
((B) nil ("1"))
+ ((E) (E "*") (B))
))
(6 (
- ((E) (E "+") (B))
((B) nil ("0"))
((B) nil ("1"))
+ ((E) (E "+") (B))
))
(7 (((E) (E "*" B) nil)))
(8 (((E) (E "+" B) nil))))
@@ -1179,7 +1180,7 @@
(defun parser-generator-lr-test ()
"Run test."
- (setq debug-on-error t)
+ ;; (setq debug-on-error t)
(parser-generator-lr-test--items-for-prefix)
(parser-generator-lr-test--items-valid-p)
- [elpa] externals/parser-generator 172d530 214/434: Improved handling of production LHS to enable multiple symbols, (continued)
- [elpa] externals/parser-generator 172d530 214/434: Improved handling of production LHS to enable multiple symbols, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator fbc8f8b 225/434: Removed dependency of hash-table of terminals for LR parser, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 870eca2 232/434: Reduced depth of GOTO-table to always use one symbol, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 5b45b2b 235/434: Improved comments, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator c2d2d0d 239/434: Fixed FIRST calculating when building lr-item sets, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator a516e3f 234/434: Started on new test for LR(2) Parser, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 06c09bc 254/434: Removed commented-out code, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator a796d8d 253/434: Added another passing unit test for k=2, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator b2193b2 251/434: GOTO-items now only contain one symbol in parse function, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator d147355 256/434: Fixed a bug in processing production RHS when loading symbols, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 8e3084b 270/434: More work LRk parser k = 0,
ELPA Syncer <=
- [elpa] externals/parser-generator 58190dc 272/434: LR Parser k=0 building correct LR items, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 0f8aa1d 265/434: Updated LRk README, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator f0cd9f6 280/434: Started on test for export parser feature, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 3e9b4ee 279/434: Improved README, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 2920af5 286/434: Parser is exported but helper-functions are missing still, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator e904d46 289/434: Moved LR-parser exporter to stand-alone file and added documentation about export, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 099304e 296/434: Some coding-styling fixes, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 5a2dbb3 297/434: Removed unnecessary debug outputs, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 99b531f 300/434: Made some cpu complexity optimizations, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 17c36f8 309/434: Added cache to lr-items for prefix function, ELPA Syncer, 2021/11/29