emacs-elpa-diffs
[Top][All Lists]
Advanced

[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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]