branch: externals/parser-generator
commit d1473552933fbd303447d8b88a397a72bb7cade1
Author: Christian Johansson <christ...@cvj.se>
Commit: Christian Johansson <christ...@cvj.se>

    Fixed a bug in processing production RHS when loading symbols
---
 parser-generator.el           | 141 +++++++++++++++++++++++++++++++-----------
 test/parser-generator-test.el |   6 +-
 2 files changed, 111 insertions(+), 36 deletions(-)

diff --git a/parser-generator.el b/parser-generator.el
index b400336..bffb37b 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
@@ -311,19 +311,42 @@
       nil)))
 
 (defun parser-generator--load-symbols ()
-  "Load terminals and non-terminals in grammar."
-  (let ((terminals (parser-generator--get-grammar-terminals)))
-    (setq parser-generator--table-terminal-p (make-hash-table :test 'equal))
+  "Load all symbols of grammar."
+
+  ;; Build hash-table of all terminals of grammar
+  (let ((terminals
+         (parser-generator--get-grammar-terminals)))
+    (setq
+     parser-generator--table-terminal-p
+     (make-hash-table :test 'equal))
     (dolist (terminal terminals)
-      (puthash terminal t parser-generator--table-terminal-p)))
+      (puthash
+       terminal
+       t
+       parser-generator--table-terminal-p)))
 
-  (let ((non-terminals (parser-generator--get-grammar-non-terminals)))
-    (setq parser-generator--table-non-terminal-p (make-hash-table :test 
'equal))
+  ;; Build hash-table of all non-terminals
+  (let ((non-terminals
+         (parser-generator--get-grammar-non-terminals)))
+    (setq
+     parser-generator--table-non-terminal-p
+     (make-hash-table :test 'equal))
     (dolist (non-terminal non-terminals)
-      (puthash non-terminal t parser-generator--table-non-terminal-p)))
+      (puthash
+       non-terminal
+       t
+       parser-generator--table-non-terminal-p)))
 
-  (let ((productions (parser-generator--get-grammar-productions)))
-    (setq parser-generator--table-productions-rhs (make-hash-table :test 
'equal))
+  (let ((productions
+         (parser-generator--get-grammar-productions)))
+
+    ;; TODO Could optimize this two loops into one
+
+    ;; Build hash-table of all right-hand-sides of
+    ;; a given left-hand-side of a production
+    (setq
+     parser-generator--table-productions-rhs
+     (make-hash-table :test 'equal))
     (dolist (p productions)
       (let ((lhs (car p))
             (rhs (cdr p)))
@@ -334,18 +357,27 @@
                 lhs
                 parser-generator--table-productions-rhs)))
           (dolist (rhs-element rhs)
-            (unless (listp rhs-element)
-              (setq rhs-element (list rhs-element)))
-            (let ((new-rhs))
-              (dolist (rhs-sub-element rhs-element)
-                (unless (functionp rhs-sub-element)
-                  (push rhs-sub-element new-rhs)))
-              (push (nreverse new-rhs) new-value)))
+            (unless (functionp rhs-element)
+              (unless (listp rhs-element)
+                (setq rhs-element (list rhs-element)))
+              (let ((new-rhs))
+                (dolist (rhs-sub-element rhs-element)
+                  (unless (functionp rhs-sub-element)
+                    (push
+                     rhs-sub-element
+                     new-rhs)))
+                (push
+                 (nreverse new-rhs)
+                 new-value))))
           (puthash
            lhs
            (nreverse new-value)
            parser-generator--table-productions-rhs))))
 
+    ;; Build hash-table of production -> production number
+    ;; and production-number -> production
+    ;; and a new set of productions that excludes translations
+    ;; and always has the left-hand-side as a list
     (setq
      parser-generator--table-productions-number
      (make-hash-table :test 'equal))
@@ -355,7 +387,8 @@
     (setq
      parser-generator--table-translations
      (make-hash-table :test 'equal))
-    (let ((production-index 0))
+    (let ((production-index 0)
+          (new-productions))
       (dolist (p productions)
         (let ((lhs (car p))
               (rhs (cdr p))
@@ -367,24 +400,45 @@
                 (rhs-length (length rhs))
                 (rhs-element))
             (while (< rhs-element-index rhs-length)
-              (setq rhs-element (nth rhs-element-index rhs))
+              (setq
+               rhs-element
+               (nth rhs-element-index rhs))
               (unless (listp rhs-element)
-                (setq rhs-element (list rhs-element)))
-
+                (setq
+                 rhs-element
+                 (list rhs-element)))
               (let ((sub-rhs-element-index 0)
                     (sub-rhs-element-length (length rhs-element))
                     (sub-rhs-element)
                     (new-rhs))
-                (while (< sub-rhs-element-index sub-rhs-element-length)
-                  (setq sub-rhs-element (nth sub-rhs-element-index 
rhs-element))
+                (while
+                    (<
+                     sub-rhs-element-index
+                     sub-rhs-element-length)
+                  (setq
+                   sub-rhs-element
+                   (nth sub-rhs-element-index rhs-element))
                   (if (functionp sub-rhs-element)
-                      (setq translation sub-rhs-element)
-                    (push sub-rhs-element new-rhs))
-                  (setq sub-rhs-element-index (1+ sub-rhs-element-index)))
-                (setq production (list lhs (nreverse new-rhs)))
+                      (setq
+                       translation
+                       sub-rhs-element)
+                    (push
+                     sub-rhs-element
+                     new-rhs))
+                  (setq
+                   sub-rhs-element-index
+                   (1+ sub-rhs-element-index)))
+                (setq
+                 production
+                 (list lhs (nreverse new-rhs)))
                 (parser-generator--debug
-                 (message "Production %s: %s" production-index production)))
-              (setq rhs-element-index (1+ rhs-element-index))
+                 (message
+                  "Production %s: %s"
+                  production-index
+                  production)))
+              (setq
+               rhs-element-index
+               (1+ rhs-element-index))
               (puthash
                production
                production-index
@@ -393,14 +447,28 @@
                production-index
                production
                parser-generator--table-productions-number-reverse)
+              (push
+               production
+               new-productions)
               (when translation
                 (parser-generator--debug
-                 (message "Translation %s: %s" production-index translation))
+                 (message
+                  "Translation %s: %s"
+                  production-index
+                  translation))
                 (puthash
                  production-index
                  translation
                  parser-generator--table-translations))
-              (setq production-index (1+ production-index))))))))
+              (setq production-index (1+ production-index))))))
+      (setq
+       new-productions
+       (nreverse new-productions))
+      (setcar
+       (nthcdr
+        2
+        parser-generator--grammar)
+       new-productions)))
 
   (let ((look-aheads
          (parser-generator--get-grammar-look-aheads)))
@@ -787,7 +855,8 @@
                       ;; If we have multiple equal LHS
                       ;; merge them
                       (when (gethash production-lhs f-set)
-                        (let ((existing-f-set (gethash production-lhs f-set)))
+                        (let ((existing-f-set
+                               (gethash production-lhs f-set)))
 
                           ;; If another set has not been fully expanded
                           ;; mark LHS as not fully expanded
@@ -966,7 +1035,7 @@
                         (when (and
                                sub-terminal-data
                                (not sub-terminal-expanded)
-                               (not (equal lhs rhs-element)))
+                               (not (equal lhs (list rhs-element))))
                           (parser-generator--debug
                            (message
                             "Expanded-all negative set 1 from %s" rhs-element))
@@ -1311,7 +1380,8 @@
   (let ((follow-set nil)
         (match-length (length β)))
     ;; Iterate all productions in grammar
-    (let ((productions (parser-generator--get-grammar-productions)))
+    (let ((productions
+           (parser-generator--get-grammar-productions)))
       (dolist (p productions)
         ;; Iterate all RHS of every production
         (let ((production-rhs (cdr p))
@@ -1346,7 +1416,8 @@
                       (setq match-index 0))))
                 (setq rhs-index (1+ rhs-index))))))))
     (when (> (length follow-set) 0)
-      (setq follow-set (parser-generator--distinct follow-set)))
+      (setq follow-set
+            (parser-generator--distinct follow-set)))
     follow-set))
 
 
diff --git a/test/parser-generator-test.el b/test/parser-generator-test.el
index 3b4b143..cdd5a0a 100644
--- a/test/parser-generator-test.el
+++ b/test/parser-generator-test.el
@@ -599,7 +599,8 @@
   "Test `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))
+  (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)
 
   (should (equal
@@ -608,6 +609,9 @@
   (should (equal
            '(("b" "a"))
            (parser-generator--get-grammar-rhs 'A)))
+  (should (equal
+           '(("b"))
+           (parser-generator--get-grammar-rhs 'B)))
 
   (parser-generator-set-grammar '((S A B) ("a" "b") ((S A) (S (B)) (B "a") (A 
"a") (A ("b" "a"))) S))
   (parser-generator-process-grammar)

Reply via email to