[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/parser-generator fe94691 048/434: Added hash-table for
From: |
ELPA Syncer |
Subject: |
[elpa] externals/parser-generator fe94691 048/434: Added hash-table for production RHS |
Date: |
Mon, 29 Nov 2021 15:59:06 -0500 (EST) |
branch: externals/parser-generator
commit fe9469199e0e98d0aaeb4470284232bfa14d5c6f
Author: Christian Johansson <christian@cvj.se>
Commit: Christian Johansson <christian@cvj.se>
Added hash-table for production RHS
---
parser.el | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 75 insertions(+), 10 deletions(-)
diff --git a/parser.el b/parser.el
index 21af745..8e9c978 100644
--- a/parser.el
+++ b/parser.el
@@ -14,14 +14,18 @@
nil
"Whether to print debug messages or not.")
-(defvar parser--table-terminal-p
- nil
- "Hash-table of non-terminals for quick checking.")
-
(defvar parser--table-non-terminal-p
nil
"Hash-table of terminals for quick checking.")
+(defvar parser--table-productions
+ nil
+ "Hash-table of productions for quick retrieving.")
+
+(defvar parser--table-terminal-p
+ nil
+ "Hash-table of non-terminals for quick checking.")
+
(defvar parser--grammar
nil
"Current grammar used in parser.")
@@ -47,6 +51,10 @@
;; Helper Functions
+(defun parser--clear-cache ()
+ "Clear cache."
+ (setq parser--f-sets nil))
+
(defun parser--distinct (elements)
"Return distinct of ELEMENTS."
(let ((processed (make-hash-table :test 'equal))
@@ -65,6 +73,10 @@
(error "No grammar G defined!")))
(nth 0 G))
+(defun parser--get-grammar-rhs (lhs)
+ "Return right hand sides of LHS if there is any."
+ (gethash lhs parser--table-productions))
+
(defun parser--get-grammar-productions (&optional G)
"Return productions of grammar G."
(unless G
@@ -98,21 +110,32 @@
(let ((non-terminals (parser--get-grammar-non-terminals)))
(setq parser--table-non-terminal-p (make-hash-table :test 'equal))
(dolist (non-terminal non-terminals)
- (puthash non-terminal t parser--table-non-terminal-p))))
+ (puthash non-terminal t parser--table-non-terminal-p)))
+ (let ((productions (parser--get-grammar-productions)))
+ (setq parser--table-productions (make-hash-table :test 'equal))
+ (dolist (p productions)
+ (let ((lhs (car p))
+ (rhs (cdr p)))
+ (dolist (rhs-element rhs)
+ (unless (listp rhs-element)
+ (setq rhs-element (list rhs-element)))
+ (let ((new-value (gethash lhs parser--table-productions)))
+ (setq new-value (append new-value rhs))
+ (puthash lhs new-value parser--table-productions)))))))
(defun parser--set-look-ahead-number (k)
"Set look-ahead number K."
(unless (parser--valid-look-ahead-number-p k)
(error "Invalid look-ahead number k!"))
(setq parser--look-ahead-number k)
- (setq parser--f-sets nil))
+ (parser--clear-cache))
(defun parser--set-grammar (G)
"Set grammar G.."
(unless (parser--valid-grammar-p G)
(error "Invalid grammar G!"))
(setq parser--grammar G)
- (setq parser--f-sets nil)
+ (parser--clear-cache)
(parser--load-symbols))
(defun parser--sort-list (a b)
@@ -622,7 +645,8 @@
(setq γ (list γ)))
(unless (parser--valid-sentential-form-p γ)
(error "Invalid sentential form γ!"))
- (let ((prefix-length (length γ)))
+ (let ((prefix-length (length γ))
+ (lr-item-exists (make-hash-table :test 'equal)))
;; 1
@@ -642,10 +666,51 @@
(setq rhs (list rhs)))
;; Add [S -> . α] to V(e)
- (push `(,production-lhs ,nil ,rhs) lr-items-e))))))
+ (push `(,production-lhs nil ,rhs e) lr-items-e)
+ (puthash `(e ,production-lhs nil ,rhs e) t
lr-item-exists))))))
;; b, c
- ;; TODO 1.b. iterate every item in v-set(e), if [A -> . Bα, u] is an
item and B -> β is in P, then foreach x in FIRST(αu) add [B -> . β, x] to
v-set(e), provided it is not already there
+ ;; 1.b. iterate every item in v-set(e), if [A -> . Bα, u] is an item
and B -> β is in P
+ ;; then foreach x in FIRST(αu) add [B -> . β, x] to v-set(e), provided
it is not already there
+ (let ((found-new t))
+
+ ;; Repeat this until no new item is found
+ (while found-new
+ (setq found-new nil)
+
+ ;; Iterate every item in V(e)
+ (dolist (item lr-items-e)
+ (let ((lhs (nth 0 item))
+ (prefix (nth 1 item))
+ (rhs (nth 2 item))
+ (suffix (nth 3 item)))
+
+ ;; Without prefix
+ (unless prefix
+
+ ;; Check if RHS starts with a non-terminal
+ (let ((rhs-first (car rhs)))
+ (when (parser--valid-terminal-p rhs-first)
+ (let ((rhs-rest (append (cdr rhs) suffix)))
+ (let ((rhs-first (parser--first rhs-rest)))
+ (message "FIRST(%s) = %s" rhs-rest rhs-first)
+
+ ;; For each production with B as LHS
+ (dolist (p productions)
+ (let ((sub-lhs (car p)))
+ (when (eq sub-lhs lhs)
+ (let ((sub-rhs (cdr p)))
+ (unless (listp sub-rhs)
+ (setq sub-rhs (list sub-rhs)))
+
+ ;; For each x in FIRST(αu) add [B -> . β, x]
to v-set(e)
+ (dolist (f rhs-first)
+ ;; Provided it is not already there
+ (unless (gethash `(e ,lhs nil ,sub-rhs ,f)
lr-item-exists)
+ (push `(,lhs nil ,sub-rhs ,f) lr-items-e)
+ (setq found-new t))))))))))))))))
+
+
;; TODO 1.c. repeat b until no more items can be added to v-set(e)
(puthash 'e lr-items-e lr-items))
- [elpa] externals/parser-generator 80cf73d 019/434: Passing tests for valid-grammar syntax, (continued)
- [elpa] externals/parser-generator 80cf73d 019/434: Passing tests for valid-grammar syntax, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator bbbdea3 034/434: More improvement of documentation, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 9d0d9e5 027/434: Various debugging, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator e644708 018/434: Improved validation of grammar syntax, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator fbb8cad 012/434: Starting a refactor, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 563cbdd 023/434: Passed FIRST tests for semi-complex grammar, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator dc78de7 025/434: Fixed page comment reference, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 3e02435 028/434: Passing complex 2 test, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 8e99d0c 035/434: Fixed typo, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator bc1ec12 036/434: Improved documentation, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator fe94691 048/434: Added hash-table for production RHS,
ELPA Syncer <=
- [elpa] externals/parser-generator afa7cb9 050/434: Added unit tests for retrieving grammar RHS, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 603df44 040/434: Added failing unit tests for (parser--sort-list), ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator aadb31a 042/434: Updated README.md about FOLLOW-sets, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 586a38e 047/434: More work on algorithm 5.8, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 00ffcde 052/434: Added TODO items, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 7e051d3 054/434: Algorithm 5.8 completed but not tested, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 8e436df 056/434: More tweaking, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator a60952c 057/434: More debugging of new algorithm, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator ab0559d 060/434: More work, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator d7f43d7 066/434: Sorting lr-items for prefix before return, ELPA Syncer, 2021/11/29