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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/parser-generator 1e0418d 295/434: Incremental parse and


From: ELPA Syncer
Subject: [elpa] externals/parser-generator 1e0418d 295/434: Incremental parse and translate of exported parser passes tests
Date: Mon, 29 Nov 2021 16:00:01 -0500 (EST)

branch: externals/parser-generator
commit 1e0418d33c46e082f6140e22a93d4acff51abad5
Author: Christian Johansson <christian@cvj.se>
Commit: Christian Johansson <christian@cvj.se>

    Incremental parse and translate of exported parser passes tests
---
 parser-generator-lr-export.el           | 632 ++++++++++++++-------------
 parser-generator-lr.el                  | 743 ++++++++++++++++----------------
 test/parser-generator-lr-export-test.el |   7 +-
 3 files changed, 710 insertions(+), 672 deletions(-)

diff --git a/parser-generator-lr-export.el b/parser-generator-lr-export.el
index 0e0c9a1..ec4cdce 100644
--- a/parser-generator-lr-export.el
+++ b/parser-generator-lr-export.el
@@ -402,68 +402,82 @@
     pushdown-list
     output
     translation
-    translation-symbol-table
+    translation-symbol-table-list
     history)
-  \"Perform a LR-parse via lex-analyzer, optionally at INPUT-TAPE-INDEX with 
PUSHDOWN-LIST, OUTPUT, TRANSLATION, TRANSLATION-SYMBOL-TABLE and HISTORY.\"
+  \"Perform a LR-parse via lex-analyzer, optionally at INPUT-TAPE-INDEX with 
PUSHDOWN-LIST, OUTPUT, TRANSLATION, TRANSLATION-SYMBOL-TABLE-LIST and HISTORY.\"
   (unless input-tape-index
     (setq input-tape-index 1))
   (unless pushdown-list
     (push 0 pushdown-list))
-  (unless translation-symbol-table
-    (setq
-     translation-symbol-table
-     (make-hash-table :test 'equal)))
-
-  (if (and
-       input-tape-index
-       (> input-tape-index 1))
-      (setq
-       %s-lex-analyzer--index
-       input-tape-index)
-    (%s-lex-analyzer--reset))
-
-  (let ((accept)
-        (pre-index 0))
-    (while (not accept)
-
-      ;; Save history when index has changed to enable incremental parsing / 
translating
-      (when
-          (>
-           %s-lex-analyzer--index
-           pre-index)
-        (push
-         `(,%s-lex-analyzer--index
-           ,pushdown-list
-           ,output
-           ,translation
-           ,translation-symbol-table)
-         history)
+  (let ((translation-symbol-table
+         (make-hash-table :test 'equal)))
+    (when translation-symbol-table-list
+      (dolist
+          (item translation-symbol-table-list)
+        (puthash
+         (nth 0 item)
+         (nth 1 item)
+         translation-symbol-table)))
+
+    (if (and
+         input-tape-index
+         (> input-tape-index 1))
         (setq
-         pre-index
-         %s-lex-analyzer--index))
-
-      ;; (1) The look-ahead string u, consisting of the next k input symbols, 
is determined.
-      (let ((look-ahead
-             (%s-lex-analyzer--peek-next-look-ahead))
-            (look-ahead-full))
-
-        ;; Save token stream indexes in separate variable if needed later
-        (setq look-ahead-full look-ahead)
-
-        ;; Create simplified look-ahead for logic below
-        (setq look-ahead nil)
-        (dolist (look-ahead-item look-ahead-full)
-          (if (listp look-ahead-item)
-              (push (car look-ahead-item) look-ahead)
-            (push look-ahead-item look-ahead)))
-        (setq look-ahead (nreverse look-ahead))
-
-        (let ((table-index
-               (car pushdown-list)))
-          (let ((action-table
-                 (gethash
-                  table-index
-                  %s--action-tables)))"
+         %s-lex-analyzer--index
+         input-tape-index)
+      (%s-lex-analyzer--reset))
+
+    (let ((accept)
+          (pre-index 0))
+      (while (not accept)
+
+        ;; Save history when index has changed to enable incremental parsing / 
translating
+        (when
+            (>
+             %s-lex-analyzer--index
+             pre-index)
+          ;; We make a copy of the hash-table here to avoid passing same
+          ;; hash-table every-time with pointer
+          (let ((translation-symbol-table-list))
+            (maphash
+             (lambda (key value)
+               (push
+                `(,key ,value)
+                translation-symbol-table-list))
+             translation-symbol-table)
+            (push
+             `(,%s-lex-analyzer--index
+               ,pushdown-list
+               ,output
+               ,translation
+               ,translation-symbol-table-list)
+             history)
+            (setq
+             pre-index
+             %s-lex-analyzer--index)))
+
+        ;; (1) The look-ahead string u, consisting of the next k input 
symbols, is determined.
+        (let ((look-ahead
+               (%s-lex-analyzer--peek-next-look-ahead))
+              (look-ahead-full))
+
+          ;; Save token stream indexes in separate variable if needed later
+          (setq look-ahead-full look-ahead)
+
+          ;; Create simplified look-ahead for logic below
+          (setq look-ahead nil)
+          (dolist (look-ahead-item look-ahead-full)
+            (if (listp look-ahead-item)
+                (push (car look-ahead-item) look-ahead)
+              (push look-ahead-item look-ahead)))
+          (setq look-ahead (nreverse look-ahead))
+
+          (let ((table-index
+                 (car pushdown-list)))
+            (let ((action-table
+                   (gethash
+                    table-index
+                    %s--action-tables)))"
                namespace
                namespace
                namespace
@@ -473,255 +487,255 @@
                namespace
                namespace))
       (insert "
-            (unless action-table
-              (error
-               \"Action-table with index %s is empty! Push-down-list: %s\"
-               table-index
-               pushdown-list))")
+              (unless action-table
+                (error
+                 \"Action-table with index %s is empty! Push-down-list: %s\"
+                 table-index
+                 pushdown-list))")
 
       (insert
        (format "
-            (let ((action-match nil)
-                  (action-table-length (length action-table))
-                  (action-index 0)
-                  (possible-look-aheads))
-
-              ;; (2) The parsing action f of the table on top of the pushdown 
list is applied to the lookahead string u.
-              (while (and
-                      (not action-match)
-                      (< action-index action-table-length))
-                (let ((action (nth action-index action-table)))
-                  (let ((action-look-ahead (car action)))
-                    (push
-                     action-look-ahead
-                     possible-look-aheads)
-                    (when
-                        (equal
-                         action-look-ahead
-                         look-ahead)
-                      (setq
-                       action-match
-                       (cdr action)))
-                    (when
-                        (and
-                         (=
-                          %s--look-ahead-number
-                          0)
-                         (not
-                          action-look-ahead))
-                      ;; LR(0) reduce actions occupy entire row
-                      ;; and is applied regardless of look-ahead
-                      (setq
-                       action-match
-                       (cdr action))))
-                  (setq
-                   action-index
-                   (1+ action-index))))
-
-              (unless action-match
-                ;; (c) If f(u) = error, we halt parsing (and, in practice
-                ;; transfer to an error recovery routine)."
+              (let ((action-match nil)
+                    (action-table-length (length action-table))
+                    (action-index 0)
+                    (possible-look-aheads))
+
+                ;; (2) The parsing action f of the table on top of the 
pushdown list is applied to the lookahead string u.
+                (while (and
+                        (not action-match)
+                        (< action-index action-table-length))
+                  (let ((action (nth action-index action-table)))
+                    (let ((action-look-ahead (car action)))
+                      (push
+                       action-look-ahead
+                       possible-look-aheads)
+                      (when
+                          (equal
+                           action-look-ahead
+                           look-ahead)
+                        (setq
+                         action-match
+                         (cdr action)))
+                      (when
+                          (and
+                           (=
+                            %s--look-ahead-number
+                            0)
+                           (not
+                            action-look-ahead))
+                        ;; LR(0) reduce actions occupy entire row
+                        ;; and is applied regardless of look-ahead
+                        (setq
+                         action-match
+                         (cdr action))))
+                    (setq
+                     action-index
+                     (1+ action-index))))
+
+                (unless action-match
+                  ;; (c) If f(u) = error, we halt parsing (and, in practice
+                  ;; transfer to an error recovery routine)."
                namespace))
       (insert "
-                (error
-                 (format
-                  \"Invalid syntax! Expected one of %s found %s at %s\"
-                  possible-look-aheads
-                  look-ahead")
+                  (error
+                   (format
+                    \"Invalid syntax! Expected one of %s found %s at %s\"
+                    possible-look-aheads
+                    look-ahead")
       (insert (format "
-                  %s-lex-analyzer--index)
-                 possible-look-aheads
-                 look-ahead
-                 %s-lex-analyzer--index))
-
-              (cond
-
-               ((equal action-match '(shift))
-                ;; (a) If f(u) = shift, then the next input symbol, say a
-                ;; is removed from the input and shifted onto the pushdown 
list.
-                ;; The goto function g of the table on top of the pushdown list
-                ;; is applied to a to determine the new table to be placed on
-                ;; top of the pushdown list. We then return to step(1). If
-                ;; there is no next input symbol or g(a) is undefined, halt
-                ;; and declare error.
-
-                (let ((a (list (car look-ahead)))
-                      (a-full (list (car look-ahead-full))))
-                  (let ((goto-table
-                         (gethash
-                          table-index
-                          %s--goto-tables)))
-                    (let ((goto-table-length (length goto-table))
-                          (goto-index 0)
-                          (searching-match t)
-                          (next-index)
-                          (possible-look-aheads))
-
-                      (while (and
-                              searching-match
-                              (< goto-index goto-table-length))
-                        (let ((goto-item (nth goto-index goto-table)))
-                          (let ((goto-item-symbol (list (car goto-item)))
-                                (goto-item-next-index (car (cdr goto-item))))
-                            (push goto-item-symbol possible-look-aheads)
-
-                            (when (equal
-                                   goto-item-symbol
-                                   a)
-                              (setq next-index goto-item-next-index)
-                              (setq searching-match nil))))
-
-                        (setq goto-index (1+ goto-index)))"
+                    %s-lex-analyzer--index)
+                   possible-look-aheads
+                   look-ahead
+                   %s-lex-analyzer--index))
+
+                (cond
+
+                 ((equal action-match '(shift))
+                  ;; (a) If f(u) = shift, then the next input symbol, say a
+                  ;; is removed from the input and shifted onto the pushdown 
list.
+                  ;; The goto function g of the table on top of the pushdown 
list
+                  ;; is applied to a to determine the new table to be placed on
+                  ;; top of the pushdown list. We then return to step(1). If
+                  ;; there is no next input symbol or g(a) is undefined, halt
+                  ;; and declare error.
+
+                  (let ((a (list (car look-ahead)))
+                        (a-full (list (car look-ahead-full))))
+                    (let ((goto-table
+                           (gethash
+                            table-index
+                            %s--goto-tables)))
+                      (let ((goto-table-length (length goto-table))
+                            (goto-index 0)
+                            (searching-match t)
+                            (next-index)
+                            (possible-look-aheads))
+
+                        (while (and
+                                searching-match
+                                (< goto-index goto-table-length))
+                          (let ((goto-item (nth goto-index goto-table)))
+                            (let ((goto-item-symbol (list (car goto-item)))
+                                  (goto-item-next-index (car (cdr goto-item))))
+                              (push goto-item-symbol possible-look-aheads)
+
+                              (when (equal
+                                     goto-item-symbol
+                                     a)
+                                (setq next-index goto-item-next-index)
+                                (setq searching-match nil))))
+
+                          (setq goto-index (1+ goto-index)))"
                       namespace
                       namespace
                       namespace))
 
       (insert "
-                      (unless next-index
-                        (error
-                         \"In shift, found no GOTO-item for %s at %s, expected 
one of %s\"
-                         a")
+                        (unless next-index
+                          (error
+                           \"In shift, found no GOTO-item for %s at %s, 
expected one of %s\"
+                           a")
       (insert
        (format "
-                         %s-lex-analyzer--index
-                         possible-look-aheads))
-
-                      ;; Maybe push both tokens here?
-                      (push (car a-full) pushdown-list)
-                      (push next-index pushdown-list)
-                      (%s-lex-analyzer--pop-token)))))
-
-               ((equal (car action-match) 'reduce)
-                ;; (b) If f(u) = reduce i and production i is A -> a,
-                ;; then 2|a| symbols are removed from the top of the pushdown
-                ;; list, and production number i is placed in the output
-                ;; buffer. A new table T' is then exposed as the top table
-                ;; of the pushdown list, and the goto function of T' is applied
-                ;; to A to determine the next table to be placed on top of the
-                ;; pushdown list. We place A and this new table on top of the
-                ;; the pushdown list and return to step (1)
-
-                (let ((production-number (car (cdr action-match))))
-
-                  (let ((production
-                         (%s--get-grammar-production-by-number
-                          production-number)))
-                    (let ((production-lhs (car production))
-                          (production-rhs (car (cdr production)))
-                          (popped-items-contents))
-                      (unless (equal
-                               production-rhs
-                               (list %s--e-identifier))
-                        (let ((pop-items (* 2 (length production-rhs)))
-                              (popped-items 0)
-                              (popped-item))
-                          (while (< popped-items pop-items)
-                            (setq popped-item (pop pushdown-list))
-                            (when (and
-                                   (listp popped-item)
-                                   (%s--valid-symbol-p
-                                    (car popped-item)))
-                              (push
-                               popped-item
-                               popped-items-contents))
-                            (setq popped-items (1+ popped-items)))))
-                      (push production-number output)
-
-                      (let ((popped-items-meta-contents)
-                            (all-expanded t))
-                        ;; Collect arguments for translation
-                        (dolist (popped-item popped-items-contents)
-                          (if (and
-                               (listp popped-item)
-                               (cdr popped-item))
-                              ;; If item is a terminal, use it's literal value
-                              (push
-                               (%s-lex-analyzer--get-function
-                                popped-item)
-                               popped-items-meta-contents)
-                            (if (gethash
+                           %s-lex-analyzer--index
+                           possible-look-aheads))
+
+                        ;; Maybe push both tokens here?
+                        (push (car a-full) pushdown-list)
+                        (push next-index pushdown-list)
+                        (%s-lex-analyzer--pop-token)))))
+
+                 ((equal (car action-match) 'reduce)
+                  ;; (b) If f(u) = reduce i and production i is A -> a,
+                  ;; then 2|a| symbols are removed from the top of the pushdown
+                  ;; list, and production number i is placed in the output
+                  ;; buffer. A new table T' is then exposed as the top table
+                  ;; of the pushdown list, and the goto function of T' is 
applied
+                  ;; to A to determine the next table to be placed on top of 
the
+                  ;; pushdown list. We place A and this new table on top of the
+                  ;; the pushdown list and return to step (1)
+
+                  (let ((production-number (car (cdr action-match))))
+
+                    (let ((production
+                           (%s--get-grammar-production-by-number
+                            production-number)))
+                      (let ((production-lhs (car production))
+                            (production-rhs (car (cdr production)))
+                            (popped-items-contents))
+                        (unless (equal
+                                 production-rhs
+                                 (list %s--e-identifier))
+                          (let ((pop-items (* 2 (length production-rhs)))
+                                (popped-items 0)
+                                (popped-item))
+                            (while (< popped-items pop-items)
+                              (setq popped-item (pop pushdown-list))
+                              (when (and
+                                     (listp popped-item)
+                                     (%s--valid-symbol-p
+                                      (car popped-item)))
+                                (push
                                  popped-item
-                                 translation-symbol-table)
+                                 popped-items-contents))
+                              (setq popped-items (1+ popped-items)))))
+                        (push production-number output)
+
+                        (let ((popped-items-meta-contents)
+                              (all-expanded t))
+                          ;; Collect arguments for translation
+                          (dolist (popped-item popped-items-contents)
+                            (if (and
+                                 (listp popped-item)
+                                 (cdr popped-item))
+                                ;; If item is a terminal, use it's literal 
value
                                 (push
-                                 (gethash
-                                  popped-item
-                                  translation-symbol-table)
+                                 (%s-lex-analyzer--get-function
+                                  popped-item)
                                  popped-items-meta-contents)
-                              (setq
-                               all-expanded
-                               nil)
-                              (push
-                               nil
-                               popped-items-meta-contents))))
-                        (setq
-                         popped-items-meta-contents
-                         (nreverse popped-items-meta-contents))
-
-                        ;; Perform translation at reduction if specified
-                        (if
-                            (%s--get-grammar-translation-by-number
-                             production-number)
-                            (let ((partial-translation
-                                   (funcall
-                                    (%s--get-grammar-translation-by-number
-                                     production-number)
-                                    popped-items-meta-contents)))
-                              (puthash
-                               production-lhs
-                               partial-translation
-                               translation-symbol-table)
-                              (setq
-                               translation
-                               partial-translation))
-
-                          ;; When no translation is specified just use 
arguments as translation
-                          (when all-expanded
-                            (let ((partial-translation
-                                   popped-items-meta-contents))
-                              (puthash
-                               production-lhs
-                               partial-translation
-                               translation-symbol-table)
-                              (setq
-                               translation
-                               partial-translation)))))
-
-                      (let ((new-table-index (car pushdown-list)))
-                        (let ((goto-table
-                               (gethash
-                                new-table-index
-                                %s--goto-tables)))
-                          (let ((goto-table-length
-                                 (length goto-table))
-                                (goto-index 0)
-                                (searching-match t)
-                                (next-index))
-
-                            (while (and
-                                    searching-match
-                                    (< goto-index goto-table-length))
-                              (let ((goto-item (nth goto-index goto-table)))
-                                (let ((goto-item-symbol (list (car goto-item)))
-                                      (goto-item-next-index (car (cdr 
goto-item))))
-
-                                  (when (equal
-                                         goto-item-symbol
-                                         production-lhs)
-                                    (setq next-index goto-item-next-index)
-                                    (setq searching-match nil))))
-
-                              (setq goto-index (1+ goto-index)))
-
-                            (when next-index
-                              (push production-lhs pushdown-list)
-                              (push next-index pushdown-list)))))))))
-
-               ((equal action-match '(accept))
-                ;;    (d) If f(u) = accept, we halt and declare the string
-                ;;    in the output buffer to be the right parse of the 
original
-                ;;    input string.
-
-                (setq accept t))"
+                              (if (gethash
+                                   popped-item
+                                   translation-symbol-table)
+                                  (push
+                                   (gethash
+                                    popped-item
+                                    translation-symbol-table)
+                                   popped-items-meta-contents)
+                                (setq
+                                 all-expanded
+                                 nil)
+                                (push
+                                 nil
+                                 popped-items-meta-contents))))
+                          (setq
+                           popped-items-meta-contents
+                           (nreverse popped-items-meta-contents))
+
+                          ;; Perform translation at reduction if specified
+                          (if
+                              (%s--get-grammar-translation-by-number
+                               production-number)
+                              (let ((partial-translation
+                                     (funcall
+                                      (%s--get-grammar-translation-by-number
+                                       production-number)
+                                      popped-items-meta-contents)))
+                                (puthash
+                                 production-lhs
+                                 partial-translation
+                                 translation-symbol-table)
+                                (setq
+                                 translation
+                                 partial-translation))
+
+                            ;; When no translation is specified just use 
arguments as translation
+                            (when all-expanded
+                              (let ((partial-translation
+                                     popped-items-meta-contents))
+                                (puthash
+                                 production-lhs
+                                 partial-translation
+                                 translation-symbol-table)
+                                (setq
+                                 translation
+                                 partial-translation)))))
+
+                        (let ((new-table-index (car pushdown-list)))
+                          (let ((goto-table
+                                 (gethash
+                                  new-table-index
+                                  %s--goto-tables)))
+                            (let ((goto-table-length
+                                   (length goto-table))
+                                  (goto-index 0)
+                                  (searching-match t)
+                                  (next-index))
+
+                              (while (and
+                                      searching-match
+                                      (< goto-index goto-table-length))
+                                (let ((goto-item (nth goto-index goto-table)))
+                                  (let ((goto-item-symbol (list (car 
goto-item)))
+                                        (goto-item-next-index (car (cdr 
goto-item))))
+
+                                    (when (equal
+                                           goto-item-symbol
+                                           production-lhs)
+                                      (setq next-index goto-item-next-index)
+                                      (setq searching-match nil))))
+
+                                (setq goto-index (1+ goto-index)))
+
+                              (when next-index
+                                (push production-lhs pushdown-list)
+                                (push next-index pushdown-list)))))))))
+
+                 ((equal action-match '(accept))
+                  ;;    (d) If f(u) = accept, we halt and declare the string
+                  ;;    in the output buffer to be the right parse of the 
original
+                  ;;    input string.
+
+                  (setq accept t))"
                namespace
                namespace
                namespace
@@ -733,22 +747,30 @@
                namespace))
 
       (insert "
-               (t (error
-                   \"Invalid action-match: %s!\"
-                   action-match))))))))
-    (unless accept
-      (error
-       \"Parsed entire string without getting accepting! Output: %s\"
-       (reverse output)))
-    (when history
-      (setq history (reverse history)))
-    (when output
-      (setq output (reverse output)))
-    (list
-     output
-     translation
-     translation-symbol-table
-     history)))\n")
+                 (t (error
+                     \"Invalid action-match: %s!\"
+                     action-match))))))))
+      (unless accept
+        (error
+         \"Parsed entire string without getting accepting! Output: %s\"
+         (reverse output)))
+      (when history
+        (setq history (reverse history)))
+      (when output
+        (setq output (reverse output)))
+      (let ((translation-symbol-table-list))
+        (when translation-symbol-table
+          (maphash
+           (lambda (key value)
+             (push
+              `(,key ,value)
+              translation-symbol-table-list))
+           translation-symbol-table))
+        (list
+         output
+         translation
+         translation-symbol-table-list
+         history)))))\n")
 
       ;; Parse
       (insert
diff --git a/parser-generator-lr.el b/parser-generator-lr.el
index 1b625f4..bb25210 100644
--- a/parser-generator-lr.el
+++ b/parser-generator-lr.el
@@ -919,397 +919,408 @@
                pushdown-list
                output
                translation
-               translation-symbol-table
+               translation-symbol-table-list
                history)
-  "Perform a LR-parse via lex-analyzer, optionally at INPUT-TAPE-INDEX with 
PUSHDOWN-LIST, OUTPUT, TRANSLATION, TRANSLATION-SYMBOL-TABLE and HISTORY."
+  "Perform a LR-parse via lex-analyzer, optionally at INPUT-TAPE-INDEX with 
PUSHDOWN-LIST, OUTPUT, TRANSLATION, TRANSLATION-SYMBOL-TABLE-LIST and HISTORY."
   (unless input-tape-index
     (setq input-tape-index 1))
   (unless pushdown-list
     (push 0 pushdown-list))
-  (unless translation-symbol-table
-    (setq
-     translation-symbol-table
-     (make-hash-table :test 'equal)))
+  (let ((translation-symbol-table
+         (make-hash-table :test 'equal)))
+    (when translation-symbol-table-list
+      (dolist
+          (item translation-symbol-table-list)
+        (puthash
+         (nth 0 item)
+         (nth 1 item)
+         translation-symbol-table)))
 
-  (if (and
-       input-tape-index
-       (> input-tape-index 1))
-      (setq
-       parser-generator-lex-analyzer--index
-       input-tape-index)
-    (parser-generator-lex-analyzer--reset))
-
-  ;; Make sure tables exists
-  (unless parser-generator-lr--action-tables
-    (error "Missing action-tables for grammar!"))
-  (unless parser-generator-lr--goto-tables
-    (error "Missing GOTO-tables for grammar!"))
-
-  (let ((accept)
-        (pre-index 0))
-    (while (not accept)
-
-      ;; Save history when index has changed to enable incremental parsing / 
translating
-      (when
-          (>
-           parser-generator-lex-analyzer--index
-           pre-index)
-        ;; We make a copy of the hash-table here to avoid passing same
-        ;; hash-table every-time with pointer
-        (let ((translation-symbol-table-copy
-               (make-hash-table :test 'equal)))
-          (maphash
-           (lambda (key value)
-             (puthash
-              key
-              value
-              translation-symbol-table-copy))
-           translation-symbol-table)
-          (push
-           `(,parser-generator-lex-analyzer--index
-             ,pushdown-list
-             ,output
-             ,translation
-             ,translation-symbol-table-copy)
-           history)
-          (setq
-           pre-index
-           parser-generator-lex-analyzer--index)))
-
-      ;; (1) The look-ahead string u, consisting of the next k input symbols, 
is determined.
-      (let ((look-ahead
-             (parser-generator-lex-analyzer--peek-next-look-ahead))
-            (look-ahead-full))
-
-        ;; Save token stream indexes in separate variable if needed later
-        (setq look-ahead-full look-ahead)
-
-        ;; Create simplified look-ahead for logic below
-        (setq look-ahead nil)
-        (dolist (look-ahead-item look-ahead-full)
-          (if (listp look-ahead-item)
-              (push (car look-ahead-item) look-ahead)
-            (push look-ahead-item look-ahead)))
-        (setq look-ahead (nreverse look-ahead))
+    (if (and
+         input-tape-index
+         (> input-tape-index 1))
+        (setq
+         parser-generator-lex-analyzer--index
+         input-tape-index)
+      (parser-generator-lex-analyzer--reset))
 
-        (parser-generator--debug
-         (message "look-ahead: %s" look-ahead)
-         (message "look-ahead-full: %s" look-ahead-full))
-
-        (let ((table-index
-               (car pushdown-list)))
-          (let ((action-table
-                 (gethash
-                  table-index
-                  parser-generator-lr--action-tables)))
-
-            (unless action-table
-              (error
-               "Action-table with index %s is empty! Push-down-list: %s"
-               table-index
-               pushdown-list))
+    ;; Make sure tables exists
+    (unless parser-generator-lr--action-tables
+      (error "Missing action-tables for grammar!"))
+    (unless parser-generator-lr--goto-tables
+      (error "Missing GOTO-tables for grammar!"))
 
-            (parser-generator--debug
-             (message
-              "Action-table %d: %s"
-              table-index
-              action-table))
-
-            (let ((action-match nil)
-                  (action-table-length (length action-table))
-                  (action-index 0)
-                  (possible-look-aheads))
-
-              ;; (2) The parsing action f of the table on top of the pushdown 
list is applied to the lookahead string u.
-              (while (and
-                      (not action-match)
-                      (< action-index action-table-length))
-                (let ((action (nth action-index action-table)))
-                  (let ((action-look-ahead (car action)))
-                    (push
-                     action-look-ahead
-                     possible-look-aheads)
-                    (when
-                        (equal
-                         action-look-ahead
-                         look-ahead)
-                      (setq
-                       action-match
-                       (cdr action)))
-                    (when
-                        (and
-                         (=
-                          parser-generator--look-ahead-number
-                          0)
-                         (not
-                          action-look-ahead))
-                      ;; LR(0) reduce actions occupy entire row
-                      ;; and is applied regardless of look-ahead
-                      (setq
-                       action-match
-                       (cdr action))))
-                  (setq
-                   action-index
-                   (1+ action-index))))
+    (let ((accept)
+          (pre-index 0))
+      (while (not accept)
 
-              (unless action-match
-                ;; (c) If f(u) = error, we halt parsing (and, in practice
-                ;; transfer to an error recovery routine).
+        ;; Save history when index has changed to enable incremental parsing / 
translating
+        (when
+            (>
+             parser-generator-lex-analyzer--index
+             pre-index)
+          ;; We make a copy of the hash-table here to avoid passing same
+          ;; hash-table every-time with pointer
+          (let ((translation-symbol-table-list))
+            (maphash
+             (lambda (key value)
+               (push
+                `(,key ,value)
+                translation-symbol-table-list))
+             translation-symbol-table)
+            (push
+             `(,parser-generator-lex-analyzer--index
+               ,pushdown-list
+               ,output
+               ,translation
+               ,translation-symbol-table-list)
+             history)
+            (setq
+             pre-index
+             parser-generator-lex-analyzer--index)))
+
+        ;; (1) The look-ahead string u, consisting of the next k input 
symbols, is determined.
+        (let ((look-ahead
+               (parser-generator-lex-analyzer--peek-next-look-ahead))
+              (look-ahead-full))
+
+          ;; Save token stream indexes in separate variable if needed later
+          (setq look-ahead-full look-ahead)
+
+          ;; Create simplified look-ahead for logic below
+          (setq look-ahead nil)
+          (dolist (look-ahead-item look-ahead-full)
+            (if (listp look-ahead-item)
+                (push (car look-ahead-item) look-ahead)
+              (push look-ahead-item look-ahead)))
+          (setq look-ahead (nreverse look-ahead))
 
+          (parser-generator--debug
+           (message "look-ahead: %s" look-ahead)
+           (message "look-ahead-full: %s" look-ahead-full))
+
+          (let ((table-index
+                 (car pushdown-list)))
+            (let ((action-table
+                   (gethash
+                    table-index
+                    parser-generator-lr--action-tables)))
+
+              (unless action-table
                 (error
-                 (format
-                  "Invalid syntax! Expected one of %s found %s at %s"
-                  possible-look-aheads
-                  look-ahead
-                  parser-generator-lex-analyzer--index)
-                 possible-look-aheads
-                 look-ahead
-                 parser-generator-lex-analyzer--index))
+                 "Action-table with index %s is empty! Push-down-list: %s"
+                 table-index
+                 pushdown-list))
 
               (parser-generator--debug
-               (message "action-table: %s" action-table)
-               (message "action-match: %s" action-match))
-
-              (cond
-
-               ((equal action-match '(shift))
-                ;; (a) If f(u) = shift, then the next input symbol, say a
-                ;; is removed from the input and shifted onto the pushdown 
list.
-                ;; The goto function g of the table on top of the pushdown list
-                ;; is applied to a to determine the new table to be placed on
-                ;; top of the pushdown list. We then return to step(1). If
-                ;; there is no next input symbol or g(a) is undefined, halt
-                ;; and declare error.
-
-                (let ((a (list (car look-ahead)))
-                      (a-full (list (car look-ahead-full))))
-                  (parser-generator--debug
-                   (message "shift a: %s" a)
-                   (message "shift a-full: %s" a-full))
-                  (let ((goto-table
-                         (gethash
-                          table-index
-                          parser-generator-lr--goto-tables)))
-                    (let ((goto-table-length (length goto-table))
-                          (goto-index 0)
-                          (searching-match t)
-                          (next-index)
-                          (possible-look-aheads))
-
-                      (while (and
-                              searching-match
-                              (< goto-index goto-table-length))
-                        (let ((goto-item (nth goto-index goto-table)))
-                          (let ((goto-item-symbol (list (car goto-item)))
-                                (goto-item-next-index (car (cdr goto-item))))
-                            (push goto-item-symbol possible-look-aheads)
+               (message
+                "Action-table %d: %s"
+                table-index
+                action-table))
 
-                            (parser-generator--debug
-                             (message "shift goto-item: %s" goto-item)
-                             (message "shift goto-item-symbol: %s" 
goto-item-symbol))
+              (let ((action-match nil)
+                    (action-table-length (length action-table))
+                    (action-index 0)
+                    (possible-look-aheads))
 
-                            (when (equal
-                                   goto-item-symbol
-                                   a)
-                              (setq next-index goto-item-next-index)
-                              (setq searching-match nil))))
+                ;; (2) The parsing action f of the table on top of the 
pushdown list is applied to the lookahead string u.
+                (while (and
+                        (not action-match)
+                        (< action-index action-table-length))
+                  (let ((action (nth action-index action-table)))
+                    (let ((action-look-ahead (car action)))
+                      (push
+                       action-look-ahead
+                       possible-look-aheads)
+                      (when
+                          (equal
+                           action-look-ahead
+                           look-ahead)
+                        (setq
+                         action-match
+                         (cdr action)))
+                      (when
+                          (and
+                           (=
+                            parser-generator--look-ahead-number
+                            0)
+                           (not
+                            action-look-ahead))
+                        ;; LR(0) reduce actions occupy entire row
+                        ;; and is applied regardless of look-ahead
+                        (setq
+                         action-match
+                         (cdr action))))
+                    (setq
+                     action-index
+                     (1+ action-index))))
+
+                (unless action-match
+                  ;; (c) If f(u) = error, we halt parsing (and, in practice
+                  ;; transfer to an error recovery routine).
+
+                  (error
+                   (format
+                    "Invalid syntax! Expected one of %s found %s at %s"
+                    possible-look-aheads
+                    look-ahead
+                    parser-generator-lex-analyzer--index)
+                   possible-look-aheads
+                   look-ahead
+                   parser-generator-lex-analyzer--index))
 
-                        (setq goto-index (1+ goto-index)))
+                (parser-generator--debug
+                 (message "action-table: %s" action-table)
+                 (message "action-match: %s" action-match))
+
+                (cond
+
+                 ((equal action-match '(shift))
+                  ;; (a) If f(u) = shift, then the next input symbol, say a
+                  ;; is removed from the input and shifted onto the pushdown 
list.
+                  ;; The goto function g of the table on top of the pushdown 
list
+                  ;; is applied to a to determine the new table to be placed on
+                  ;; top of the pushdown list. We then return to step(1). If
+                  ;; there is no next input symbol or g(a) is undefined, halt
+                  ;; and declare error.
+
+                  (let ((a (list (car look-ahead)))
+                        (a-full (list (car look-ahead-full))))
+                    (parser-generator--debug
+                     (message "shift a: %s" a)
+                     (message "shift a-full: %s" a-full))
+                    (let ((goto-table
+                           (gethash
+                            table-index
+                            parser-generator-lr--goto-tables)))
+                      (let ((goto-table-length (length goto-table))
+                            (goto-index 0)
+                            (searching-match t)
+                            (next-index)
+                            (possible-look-aheads))
+
+                        (while (and
+                                searching-match
+                                (< goto-index goto-table-length))
+                          (let ((goto-item (nth goto-index goto-table)))
+                            (let ((goto-item-symbol (list (car goto-item)))
+                                  (goto-item-next-index (car (cdr goto-item))))
+                              (push goto-item-symbol possible-look-aheads)
 
-                      (parser-generator--debug
-                       (message "shift next-index: %s" next-index))
-
-                      (unless next-index
-                        (error
-                         "In shift, found no GOTO-item for %s at %s, expected 
one of %s"
-                         a
-                         parser-generator-lex-analyzer--index
-                         possible-look-aheads))
-
-                      ;; Maybe push both tokens here?
-                      (push (car a-full) pushdown-list)
-                      (push next-index pushdown-list)
-                      (parser-generator-lex-analyzer--pop-token)))))
-
-               ((equal (car action-match) 'reduce)
-                ;; (b) If f(u) = reduce i and production i is A -> a,
-                ;; then 2|a| symbols are removed from the top of the pushdown
-                ;; list, and production number i is placed in the output
-                ;; buffer. A new table T' is then exposed as the top table
-                ;; of the pushdown list, and the goto function of T' is applied
-                ;; to A to determine the next table to be placed on top of the
-                ;; pushdown list. We place A and this new table on top of the
-                ;; the pushdown list and return to step (1)
-
-                (let ((production-number (car (cdr action-match))))
-
-                  (let ((production
-                         (parser-generator--get-grammar-production-by-number
-                          production-number)))
-                    (let ((production-lhs (car production))
-                          (production-rhs (car (cdr production)))
-                          (popped-items-contents))
-                      (parser-generator--debug
-                       (message "production-lhs: %s" production-lhs)
-                       (message "production-rhs: %s" production-rhs))
-                      (unless (equal
-                               production-rhs
-                               (list parser-generator--e-identifier))
-                        (let ((pop-items (* 2 (length production-rhs)))
-                              (popped-items 0)
-                              (popped-item))
-                          (while (< popped-items pop-items)
-                            (setq popped-item (pop pushdown-list))
+                              (parser-generator--debug
+                               (message "shift goto-item: %s" goto-item)
+                               (message "shift goto-item-symbol: %s" 
goto-item-symbol))
+
+                              (when (equal
+                                     goto-item-symbol
+                                     a)
+                                (setq next-index goto-item-next-index)
+                                (setq searching-match nil))))
+
+                          (setq goto-index (1+ goto-index)))
+
+                        (parser-generator--debug
+                         (message "shift next-index: %s" next-index))
+
+                        (unless next-index
+                          (error
+                           "In shift, found no GOTO-item for %s at %s, 
expected one of %s"
+                           a
+                           parser-generator-lex-analyzer--index
+                           possible-look-aheads))
+
+                        ;; Maybe push both tokens here?
+                        (push (car a-full) pushdown-list)
+                        (push next-index pushdown-list)
+                        (parser-generator-lex-analyzer--pop-token)))))
+
+                 ((equal (car action-match) 'reduce)
+                  ;; (b) If f(u) = reduce i and production i is A -> a,
+                  ;; then 2|a| symbols are removed from the top of the pushdown
+                  ;; list, and production number i is placed in the output
+                  ;; buffer. A new table T' is then exposed as the top table
+                  ;; of the pushdown list, and the goto function of T' is 
applied
+                  ;; to A to determine the next table to be placed on top of 
the
+                  ;; pushdown list. We place A and this new table on top of the
+                  ;; the pushdown list and return to step (1)
+
+                  (let ((production-number (car (cdr action-match))))
+
+                    (let ((production
+                           (parser-generator--get-grammar-production-by-number
+                            production-number)))
+                      (let ((production-lhs (car production))
+                            (production-rhs (car (cdr production)))
+                            (popped-items-contents))
+                        (parser-generator--debug
+                         (message "production-lhs: %s" production-lhs)
+                         (message "production-rhs: %s" production-rhs))
+                        (unless (equal
+                                 production-rhs
+                                 (list parser-generator--e-identifier))
+                          (let ((pop-items (* 2 (length production-rhs)))
+                                (popped-items 0)
+                                (popped-item))
+                            (while (< popped-items pop-items)
+                              (setq popped-item (pop pushdown-list))
+                              (parser-generator--debug
+                               (message "popped-item: %s" popped-item))
+                              (when (and
+                                     (listp popped-item)
+                                     (parser-generator--valid-symbol-p
+                                      (car popped-item)))
+                                (push
+                                 popped-item
+                                 popped-items-contents))
+                              (setq popped-items (1+ popped-items)))))
+                        (push production-number output)
+
+                        (let ((popped-items-meta-contents)
+                              (all-expanded t))
+                          ;; Collect arguments for translation
+                          (dolist (popped-item popped-items-contents)
                             (parser-generator--debug
-                             (message "popped-item: %s" popped-item))
-                            (when (and
-                                   (listp popped-item)
-                                   (parser-generator--valid-symbol-p
-                                    (car popped-item)))
-                              (push
-                               popped-item
-                               popped-items-contents))
-                            (setq popped-items (1+ popped-items)))))
-                      (push production-number output)
-
-                      (let ((popped-items-meta-contents)
-                            (all-expanded t))
-                        ;; Collect arguments for translation
-                        (dolist (popped-item popped-items-contents)
+                             (message
+                              "popped-item: %s"
+                              popped-item))
+                            (if (and
+                                 (listp popped-item)
+                                 (cdr popped-item))
+                                ;; If item is a terminal, use it's literal 
value
+                                (push
+                                 (parser-generator-lex-analyzer--get-function
+                                  popped-item)
+                                 popped-items-meta-contents)
+                              (if (gethash
+                                   popped-item
+                                   translation-symbol-table)
+                                  (push
+                                   (gethash
+                                    popped-item
+                                    translation-symbol-table)
+                                   popped-items-meta-contents)
+                                (setq
+                                 all-expanded
+                                 nil)
+                                (push
+                                 nil
+                                 popped-items-meta-contents))))
+                          (setq
+                           popped-items-meta-contents
+                           (nreverse popped-items-meta-contents))
                           (parser-generator--debug
                            (message
-                            "popped-item: %s"
-                            popped-item))
-                          (if (and
-                               (listp popped-item)
-                               (cdr popped-item))
-                              ;; If item is a terminal, use it's literal value
-                              (push
-                               (parser-generator-lex-analyzer--get-function
-                                popped-item)
-                               popped-items-meta-contents)
-                            (if (gethash
-                                 popped-item
+                            "Production arguments: %s -> %s = %s"
+                            production-lhs
+                            production-rhs
+                            popped-items-meta-contents))
+
+                          ;; Perform translation at reduction if specified
+                          (if
+                              
(parser-generator--get-grammar-translation-by-number
+                               production-number)
+                              (let ((partial-translation
+                                     (funcall
+                                      
(parser-generator--get-grammar-translation-by-number
+                                       production-number)
+                                      popped-items-meta-contents)))
+                                (parser-generator--debug
+                                 (message
+                                  "translation-symbol-table: %s = %s"
+                                  production-lhs
+                                  partial-translation))
+                                (puthash
+                                 production-lhs
+                                 partial-translation
                                  translation-symbol-table)
-                                (push
-                                 (gethash
-                                  popped-item
-                                  translation-symbol-table)
-                                 popped-items-meta-contents)
-                              (setq
-                               all-expanded
-                               nil)
-                              (push
-                               nil
-                               popped-items-meta-contents))))
-                        (setq
-                         popped-items-meta-contents
-                         (nreverse popped-items-meta-contents))
-                        (parser-generator--debug
-                         (message
-                          "Production arguments: %s -> %s = %s"
-                          production-lhs
-                          production-rhs
-                          popped-items-meta-contents))
-
-                        ;; Perform translation at reduction if specified
-                        (if
-                            
(parser-generator--get-grammar-translation-by-number
-                             production-number)
-                            (let ((partial-translation
-                                   (funcall
-                                    
(parser-generator--get-grammar-translation-by-number
-                                     production-number)
-                                    popped-items-meta-contents)))
-                              (parser-generator--debug
-                               (message
-                                "translation-symbol-table: %s = %s"
-                                production-lhs
-                                partial-translation))
-                              (puthash
-                               production-lhs
-                               partial-translation
-                               translation-symbol-table)
-                              (setq
-                               translation
-                               partial-translation))
+                                (setq
+                                 translation
+                                 partial-translation))
+
+                            ;; When no translation is specified just use 
arguments as translation
+                            (when all-expanded
+                              (let ((partial-translation
+                                     popped-items-meta-contents))
+                                (parser-generator--debug
+                                 (message
+                                  "translation-symbol-table: %s = %s (generic)"
+                                  production-lhs
+                                  partial-translation))
+                                (puthash
+                                 production-lhs
+                                 partial-translation
+                                 translation-symbol-table)
+                                (setq
+                                 translation
+                                 partial-translation)))))
 
-                          ;; When no translation is specified just use 
arguments as translation
-                          (when all-expanded
-                            (let ((partial-translation
-                                   popped-items-meta-contents))
-                              (parser-generator--debug
-                               (message
-                                "translation-symbol-table: %s = %s (generic)"
-                                production-lhs
-                                partial-translation))
-                              (puthash
-                               production-lhs
-                               partial-translation
-                               translation-symbol-table)
-                              (setq
-                               translation
-                               partial-translation)))))
-
-                      (let ((new-table-index (car pushdown-list)))
-                        (let ((goto-table
-                               (gethash
-                                new-table-index
-                                parser-generator-lr--goto-tables)))
-                          (let ((goto-table-length
-                                 (length goto-table))
-                                (goto-index 0)
-                                (searching-match t)
-                                (next-index))
-
-                            (while (and
-                                    searching-match
-                                    (< goto-index goto-table-length))
-                              (let ((goto-item (nth goto-index goto-table)))
-                                (let ((goto-item-symbol (list (car goto-item)))
-                                      (goto-item-next-index (car (cdr 
goto-item))))
-                                  (parser-generator--debug
-                                   (message "reduce goto-item: %s" goto-item)
-                                   (message "reduce goto-item-symbol: %s" 
goto-item-symbol))
+                        (let ((new-table-index (car pushdown-list)))
+                          (let ((goto-table
+                                 (gethash
+                                  new-table-index
+                                  parser-generator-lr--goto-tables)))
+                            (let ((goto-table-length
+                                   (length goto-table))
+                                  (goto-index 0)
+                                  (searching-match t)
+                                  (next-index))
+
+                              (while (and
+                                      searching-match
+                                      (< goto-index goto-table-length))
+                                (let ((goto-item (nth goto-index goto-table)))
+                                  (let ((goto-item-symbol (list (car 
goto-item)))
+                                        (goto-item-next-index (car (cdr 
goto-item))))
+                                    (parser-generator--debug
+                                     (message "reduce goto-item: %s" goto-item)
+                                     (message "reduce goto-item-symbol: %s" 
goto-item-symbol))
 
-                                  (when (equal
-                                         goto-item-symbol
-                                         production-lhs)
-                                    (setq next-index goto-item-next-index)
-                                    (setq searching-match nil))))
+                                    (when (equal
+                                           goto-item-symbol
+                                           production-lhs)
+                                      (setq next-index goto-item-next-index)
+                                      (setq searching-match nil))))
 
-                              (setq goto-index (1+ goto-index)))
+                                (setq goto-index (1+ goto-index)))
 
-                            (parser-generator--debug
-                             (message "reduce next-index: %s" next-index))
-
-                            (when next-index
-                              (push production-lhs pushdown-list)
-                              (push next-index pushdown-list)))))))))
-
-               ((equal action-match '(accept))
-                ;;    (d) If f(u) = accept, we halt and declare the string
-                ;;    in the output buffer to be the right parse of the 
original
-                ;;    input string.
-
-                (setq accept t))
-
-               (t (error
-                   "Invalid action-match: %s!"
-                   action-match))))))))
-    (unless accept
-      (error
-       "Parsed entire string without getting accepting! Output: %s"
-       (reverse output)))
-    (when history
-      (setq history (reverse history)))
-    (when output
-      (setq output (reverse output)))
-    (list
-     output
-     translation
-     translation-symbol-table
-     history)))
+                              (parser-generator--debug
+                               (message "reduce next-index: %s" next-index))
+
+                              (when next-index
+                                (push production-lhs pushdown-list)
+                                (push next-index pushdown-list)))))))))
+
+                 ((equal action-match '(accept))
+                  ;;    (d) If f(u) = accept, we halt and declare the string
+                  ;;    in the output buffer to be the right parse of the 
original
+                  ;;    input string.
+
+                  (setq accept t))
+
+                 (t (error
+                     "Invalid action-match: %s!"
+                     action-match))))))))
+      (unless accept
+        (error
+         "Parsed entire string without getting accepting! Output: %s"
+         (reverse output)))
+      (when history
+        (setq history (reverse history)))
+      (when output
+        (setq output (reverse output)))
+      (let ((translation-symbol-table-list))
+        (when translation-symbol-table
+          (maphash
+           (lambda (key value)
+             (push
+              `(,key ,value)
+              translation-symbol-table-list))
+           translation-symbol-table))
+        (list
+         output
+         translation
+         translation-symbol-table-list
+         history)))))
 
 (provide 'parser-generator-lr)
 
diff --git a/test/parser-generator-lr-export-test.el 
b/test/parser-generator-lr-export-test.el
index 11b644c..92bf701 100644
--- a/test/parser-generator-lr-export-test.el
+++ b/test/parser-generator-lr-export-test.el
@@ -60,9 +60,13 @@
         (should
          (equal
           t
+          (fboundp 'ba-parse)))
+        (should
+         (equal
+          t
           (fboundp 'ba-translate))))
 
-      (when (fboundp 'pa-translate)
+      (when (fboundp 'ba-parse)
         (should
          (equal
           '(2 2 2 1 1)
@@ -164,6 +168,7 @@
   ;; Export parser
   (let ((export (parser-generator-lr-export-to-elisp "e--")))
 
+    (message "export:\n%s\n" export)
     (with-temp-buffer
       (insert export)
       (eval-buffer)



reply via email to

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