[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/parser-generator 01173e2 230/434: Added EOF identifier,
From: |
ELPA Syncer |
Subject: |
[elpa] externals/parser-generator 01173e2 230/434: Added EOF identifier, passing all unit tests |
Date: |
Mon, 29 Nov 2021 15:59:47 -0500 (EST) |
branch: externals/parser-generator
commit 01173e2caffeb8c6efef107b762ba65191fed411
Author: Christian Johansson <christian@cvj.se>
Commit: Christian Johansson <christian@cvj.se>
Added EOF identifier, passing all unit tests
---
parser-generator-lex-analyzer.el | 2 +-
parser-generator-lr.el | 38 +-
parser-generator.el | 38 +-
test/parser-generator-lex-analyzer-test.el | 2 +-
test/parser-generator-lr-test.el | 1061 ++++++++++++++--------------
test/parser-generator-test.el | 14 +-
6 files changed, 572 insertions(+), 583 deletions(-)
diff --git a/parser-generator-lex-analyzer.el b/parser-generator-lex-analyzer.el
index 16d4714..634079b 100644
--- a/parser-generator-lex-analyzer.el
+++ b/parser-generator-lex-analyzer.el
@@ -83,7 +83,7 @@
(push next-look-ahead-item look-ahead)
(setq look-ahead-length (1+ look-ahead-length))
(setq index (cdr (cdr next-look-ahead-item))))))
- (push (list parser-generator--e-identifier) look-ahead)
+ (push (list parser-generator--eof-identifier) look-ahead)
(setq look-ahead-length (1+ look-ahead-length))
(setq index (1+ index)))))
(error (error
diff --git a/parser-generator-lr.el b/parser-generator-lr.el
index 369b4eb..1129844 100644
--- a/parser-generator-lr.el
+++ b/parser-generator-lr.el
@@ -53,6 +53,7 @@
(let ((lr-items
(gethash goto-index table-lr-items)))
(let ((lr-items-length (length lr-items)))
+
;; Where u is in (T U e)*k
(dolist (state states)
(let ((lr-item)
@@ -136,7 +137,7 @@
(if (and
(= production-number 0)
(>= (length u) 1)
- (parser-generator--valid-e-p
+ (parser-generator--valid-eof-p
(nth (1- (length u)) u)))
(progn
;; Reduction by first production
@@ -406,13 +407,21 @@
(parser-generator--get-grammar-rhs start))
(e-list (parser-generator--generate-list-of-symbol
parser-generator--look-ahead-number
- parser-generator--e-identifier)))
+ parser-generator--e-identifier))
+ (eof-list (parser-generator--generate-list-of-symbol
+ parser-generator--look-ahead-number
+ parser-generator--eof-identifier)))
;; (a)
(dolist (rhs start-productions)
;; Add [S -> . α] to V(e)
- (push `(,(list start) nil ,rhs ,e-list) lr-items-e)
- (puthash `(,e-list ,(list start) nil ,rhs ,e-list) 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
@@ -439,11 +448,12 @@
(parser-generator--valid-non-terminal-p
rhs-first)
(let ((rhs-rest (append (cdr rhs) suffix)))
- (let ((rhs-rest-first (parser-generator--first
rhs-rest)))
+ (let ((rhs-rest-first
+ (parser-generator--first rhs-rest)))
(parser-generator--debug
(message "rhs-rest-first: %s" rhs-rest-first))
(unless rhs-rest-first
- (setq rhs-rest-first `(,e-list)))
+ (setq rhs-rest-first `(,eof-list)))
(let ((sub-production
(parser-generator--get-grammar-rhs
rhs-first)))
@@ -470,10 +480,10 @@
;; Add [B -> . β, x] to V(e), provided it is
not already there
(unless
(gethash
- `(e ,(list rhs-first) nil ,sub-rhs ,f)
+ `(,e-list ,(list rhs-first) nil ,sub-rhs
,f)
lr-item-exists)
(puthash
- `(e ,(list rhs-first) nil ,sub-rhs ,f)
+ `(,e-list ,(list rhs-first) nil ,sub-rhs ,f)
t
lr-item-exists)
(push
@@ -488,7 +498,9 @@
(setq
lr-items-e
- (sort lr-items-e 'parser-generator--sort-list))
+ (sort
+ lr-items-e
+ 'parser-generator--sort-list))
;; 2 Suppose that we have constructed V(X1,X2,...,Xi-1) we construct
V(X1,X2,...,Xi) as follows:
;; Only do this step if prefix is not the e-identifier
@@ -717,13 +729,7 @@
(error "Missing GOTO-tables for grammar!"))
(let ((accept)
- (pre-index 0)
- (e-list
- (parser-generator--generate-list-of-symbol
- parser-generator--look-ahead-number
- parser-generator--e-identifier)))
- (parser-generator--debug
- (message "e-list: %s" e-list))
+ (pre-index 0))
(while (not accept)
diff --git a/parser-generator.el b/parser-generator.el
index 37152f7..a6de4c8 100644
--- a/parser-generator.el
+++ b/parser-generator.el
@@ -18,6 +18,10 @@
'e
"The identifier used for e-symbol. Default value 'e.")
+(defvar parser-generator--eof-identifier
+ '$
+ "The identifier used for end of file identifier. Default value is '$.")
+
(defvar parser-generator--grammar
nil
"Current grammar used in parser.")
@@ -113,13 +117,17 @@
(terminal-index)
(look-ahead-length)
(look-ahead)
- (e-list))
-
- (let ((e-list-index 0)
- (e-list-length parser-generator--look-ahead-number))
- (while (< e-list-index e-list-length)
- (push parser-generator--e-identifier e-list)
- (setq e-list-index (1+ e-list-index))))
+ (eof-list))
+
+ (let ((eof-list-index 0)
+ (eof-list-length parser-generator--look-ahead-number))
+ (while (< eof-list-index eof-list-length)
+ (push
+ parser-generator--eof-identifier
+ eof-list)
+ (setq
+ eof-list-index
+ (1+ eof-list-index))))
(while stack
(let ((item (pop stack)))
@@ -147,12 +155,17 @@
(if look-ahead
(progn
+ ;; If length of look-ahead is below k, append EOF identifiers
(while (< look-ahead-length k)
- (push parser-generator--e-identifier look-ahead)
- (setq look-ahead-length (1+ look-ahead-length)))
+ (push
+ parser-generator--eof-identifier
+ look-ahead)
+ (setq
+ look-ahead-length
+ (1+ look-ahead-length)))
(setq look-ahead-to-add (reverse look-ahead)))
- (setq look-ahead-to-add e-list))
+ (setq look-ahead-to-add eof-list))
(when (and look-ahead-to-add
(not (gethash look-ahead-to-add added-look-aheads)))
@@ -448,6 +461,10 @@
"Return whether SYMBOL is the e identifier or not."
(eq symbol parser-generator--e-identifier))
+(defun parser-generator--valid-eof-p (symbol)
+ "Return whether SYMBOL is the EOF identifier or not."
+ (eq symbol parser-generator--eof-identifier))
+
(defun parser-generator--valid-grammar-p (G)
"Return if grammar G is valid or not. Grammar should contain list with 4
elements: non-terminals (N), terminals (T), productions (P), start (S) where N,
T and P are lists containing symbols and/or strings and S is a symbol or
string."
(let ((valid-p t))
@@ -636,6 +653,7 @@
(let ((is-valid t))
(unless (or
(parser-generator--valid-e-p symbol)
+ (parser-generator--valid-eof-p symbol)
(parser-generator--valid-non-terminal-p symbol)
(parser-generator--valid-terminal-p symbol))
(setq is-valid nil))
diff --git a/test/parser-generator-lex-analyzer-test.el
b/test/parser-generator-lex-analyzer-test.el
index e86f8f8..ea93b8f 100644
--- a/test/parser-generator-lex-analyzer-test.el
+++ b/test/parser-generator-lex-analyzer-test.el
@@ -58,7 +58,7 @@
(setq parser-generator--look-ahead-number 10)
(should
(equal
- '(("a" 1 . 2) ("b" 2 . 3) ("c" 3 . 4) ("d" 4 . 5) (e) (e) (e) (e) (e) (e))
+ '(("a" 1 . 2) ("b" 2 . 3) ("c" 3 . 4) ("d" 4 . 5) ($) ($) ($) ($) ($) ($))
(parser-generator-lex-analyzer--peek-next-look-ahead)))
(setq
diff --git a/test/parser-generator-lr-test.el b/test/parser-generator-lr-test.el
index 79b537a..46f203c 100644
--- a/test/parser-generator-lr-test.el
+++ b/test/parser-generator-lr-test.el
@@ -61,45 +61,17 @@
(parser-generator-set-grammar '((Sp S) (a b) ((Sp S) (S (S a S b)) (S e))
Sp))
(parser-generator-set-look-ahead-number 1)
(parser-generator-process-grammar)
- (let ((table-lr-items (parser-generator-lr-generate-parser-tables)))
-
- (should
- (equal
- '((0 (((S) 1)))
- (1 (((a) 2)))
- (2 (((S) 3)))
- (3 (((a) 4) ((b) 5)))
- (4 (((S) 6)))
- (5 nil)
- (6 (((a) 4) ((b) 7)))
- (7 nil))
- (parser-generator--hash-to-list
- parser-generator-lr--goto-tables)))
- (message "Passed GOTO-tables")
-
- (should
- (equal
- '((0 (((S) nil (S a S b) (a)) ((S) nil (S a S b) (e)) ((S) nil nil (a))
((S) nil nil (e)) ((Sp) nil (S) (e))))
- (1 (((S) (S) (a S b) (a)) ((S) (S) (a S b) (e)) ((Sp) (S) nil (e))))
- (2 (((S) (S a) (S b) (a)) ((S) (S a) (S b) (e)) ((S) nil (S a S b)
(a)) ((S) nil (S a S b) (b)) ((S) nil nil (a)) ((S) nil nil (b))))
- (3 (((S) (S) (a S b) (a)) ((S) (S) (a S b) (b)) ((S) (S a S) (b) (a))
((S) (S a S) (b) (e))))
- (4 (((S) (S a) (S b) (a)) ((S) (S a) (S b) (b)) ((S) nil (S a S b)
(a)) ((S) nil (S a S b) (b)) ((S) nil nil (a)) ((S) nil nil (b))))
- (5 (((S) (S a S b) nil (a)) ((S) (S a S b) nil (e))))
- (6 (((S) (S) (a S b) (a)) ((S) (S) (a S b) (b)) ((S) (S a S) (b) (a))
((S) (S a S) (b) (b))))
- (7 (((S) (S a S b) nil (a)) ((S) (S a S b) nil (b)))))
- (parser-generator--hash-to-list
- table-lr-items)))
- (message "Passed LR-items"))
+ (parser-generator-lr-generate-parser-tables)
- ;; Fig. 5.9 p. 374
+ ;; Fig. 5.9 p. 374, replaced e with $
(should
(equal
- '((0 (((a) reduce 2) ((e) reduce 2)))
- (1 (((a) shift) ((e) accept)))
+ '((0 ((($) reduce 2) ((a) reduce 2)))
+ (1 ((($) accept) ((a) shift)))
(2 (((a) reduce 2) ((b) reduce 2)))
(3 (((a) shift) ((b) shift)))
(4 (((a) reduce 2) ((b) reduce 2)))
- (5 (((a) reduce 1) ((e) reduce 1)))
+ (5 ((($) reduce 1) ((a) reduce 1)))
(6 (((a) shift) ((b) shift)))
(7 (((a) reduce 1) ((b) reduce 1))))
(parser-generator--hash-to-list
@@ -118,595 +90,590 @@
'((Sp S) (a b) ((Sp S) (S (S a S b)) (S e)) Sp))
(parser-generator-set-look-ahead-number 1)
(parser-generator-process-grammar)
- (let ((table-lr-items (parser-generator-lr--generate-goto-tables)))
+ (let ((table-lr-items
+ (parser-generator-lr--generate-goto-tables)))
(parser-generator--debug
(message
"GOTO-table: %s"
(parser-generator--hash-to-list
parser-generator-lr--goto-tables))
+ (should
+ (equal
+ '((0 (((S) 1)))
+ (1 (((a) 2)))
+ (2 (((S) 3)))
+ (3 (((a) 4) ((b) 5)))
+ (4 (((S) 6)))
+ (5 nil)
+ (6 (((a) 4) ((b) 7)))
+ (7 nil))
+ (parser-generator--hash-to-list
+ parser-generator-lr--goto-tables)))
+ (message "Passed GOTO-tables")
+
(message
"LR-items: %s"
(parser-generator--hash-to-list
table-lr-items)))
-
- (parser-generator-lr--generate-action-tables
- table-lr-items)
- (parser-generator--debug
- (message
- "ACTION-tables: %s"
- (parser-generator--hash-to-list
- parser-generator-lr--action-tables)))
-
- (should
- (equal
- '((0 (((S) 1)))
- (1 (((a) 2)))
- (2 (((S) 3)))
- (3 (((a) 4) ((b) 5)))
- (4 (((S) 6)))
- (5 nil)
- (6 (((a) 4) ((b) 7)))
- (7 nil))
- (parser-generator--hash-to-list
- parser-generator-lr--goto-tables)))
- (message "Passed GOTO-tables")
-
(should
(equal
- '((0 (((S) nil (S a S b) (a)) ((S) nil (S a S b) (e)) ((S) nil nil (a))
((S) nil nil (e)) ((Sp) nil (S) (e))))
- (1 (((S) (S) (a S b) (a)) ((S) (S) (a S b) (e)) ((Sp) (S) nil (e))))
- (2 (((S) (S a) (S b) (a)) ((S) (S a) (S b) (e)) ((S) nil (S a S b)
(a)) ((S) nil (S a S b) (b)) ((S) nil nil (a)) ((S) nil nil (b))))
- (3 (((S) (S) (a S b) (a)) ((S) (S) (a S b) (b)) ((S) (S a S) (b) (a))
((S) (S a S) (b) (e))))
+ '((0 (((S) nil (S a S b) ($)) ((S) nil (S a S b) (a)) ((S) nil nil ($))
((S) nil nil (a)) ((Sp) nil (S) ($))))
+ (1 (((S) (S) (a S b) ($)) ((S) (S) (a S b) (a)) ((Sp) (S) nil ($))))
+ (2 (((S) (S a) (S b) ($)) ((S) (S a) (S b) (a)) ((S) nil (S a S b)
(a)) ((S) nil (S a S b) (b)) ((S) nil nil (a)) ((S) nil nil (b))))
+ (3 (((S) (S) (a S b) (a)) ((S) (S) (a S b) (b)) ((S) (S a S) (b) ($))
((S) (S a S) (b) (a))))
(4 (((S) (S a) (S b) (a)) ((S) (S a) (S b) (b)) ((S) nil (S a S b)
(a)) ((S) nil (S a S b) (b)) ((S) nil nil (a)) ((S) nil nil (b))))
- (5 (((S) (S a S b) nil (a)) ((S) (S a S b) nil (e))))
+ (5 (((S) (S a S b) nil ($)) ((S) (S a S b) nil (a))))
(6 (((S) (S) (a S b) (a)) ((S) (S) (a S b) (b)) ((S) (S a S) (b) (a))
((S) (S a S) (b) (b))))
(7 (((S) (S a S b) nil (a)) ((S) (S a S b) nil (b)))))
(parser-generator--hash-to-list
- table-lr-items))))
- (message "Passed LR-items")
+ table-lr-items)))
+ (message "Passed LR-items"))
- (message "Passed LR-items for example 5.30")
+ (message "Passed LR-items for example 5.30")
- ;; Example 5.30, p. 389 but with terminals as strings
- (parser-generator-set-grammar
- '((Sp S) ("a" "b") ((Sp S) (S (S "a" S "b")) (S e)) Sp))
- (parser-generator-set-look-ahead-number 1)
- (parser-generator-process-grammar)
-
- (let ((table-lr-items
- (parser-generator-lr-generate-parser-tables)))
+ ;; Example 5.30, p. 389 but with terminals as strings
+ (parser-generator-set-grammar
+ '((Sp S) ("a" "b") ((Sp S) (S (S "a" S "b")) (S e)) Sp))
+ (parser-generator-set-look-ahead-number 1)
+ (parser-generator-process-grammar)
- ;; (message "GOTO-table: %s" (parser-generator--hash-to-list
parser-generator-lr--goto-tables))
- ;; (message "LR-items: %s" (parser-generator--hash-to-list
parser-generator-lr--items))
+ (let ((table-lr-items
+ (parser-generator-lr--generate-goto-tables)))
+
+ ;; (message "GOTO-table: %s" (parser-generator--hash-to-list
parser-generator-lr--goto-tables))
+ ;; (message "LR-items: %s" (parser-generator--hash-to-list
parser-generator-lr--items))
+
+ (should
+ (equal
+ '((0 (((S) 1)))
+ (1 ((("a") 2)))
+ (2 (((S) 3)))
+ (3 ((("a") 4) (("b") 5)))
+ (4 (((S) 6)))
+ (5 nil)
+ (6 ((("a") 4) (("b") 7)))
+ (7 nil))
+ (parser-generator--hash-to-list
+ parser-generator-lr--goto-tables)))
+ (message "Passed GOTO-tables with tokens as strings")
+
+ (should
+ (equal
+ '((0 (((S) nil (S "a" S "b") ($)) ((S) nil (S "a" S "b") ("a")) ((S)
nil nil ($)) ((S) nil nil ("a")) ((Sp) nil (S) ($))))
+ (1 (((S) (S) ("a" S "b") ($)) ((S) (S) ("a" S "b") ("a")) ((Sp) (S)
nil ($))))
+ (2 (((S) (S "a") (S "b") ($)) ((S) (S "a") (S "b") ("a")) ((S) nil
(S "a" S "b") ("a")) ((S) nil (S "a" S "b") ("b")) ((S) nil nil ("a")) ((S) nil
nil ("b"))))
+ (3 (((S) (S) ("a" S "b") ("a")) ((S) (S) ("a" S "b") ("b")) ((S) (S
"a" S) ("b") ($)) ((S) (S "a" S) ("b") ("a"))))
+ (4 (((S) (S "a") (S "b") ("a")) ((S) (S "a") (S "b") ("b")) ((S) nil
(S "a" S "b") ("a")) ((S) nil (S "a" S "b") ("b")) ((S) nil nil ("a")) ((S) nil
nil ("b"))))
+ (5 (((S) (S "a" S "b") nil ($)) ((S) (S "a" S "b") nil ("a"))))
+ (6 (((S) (S) ("a" S "b") ("a")) ((S) (S) ("a" S "b") ("b")) ((S) (S
"a" S) ("b") ("a")) ((S) (S "a" S) ("b") ("b"))))
+ (7 (((S) (S "a" S "b") nil ("a")) ((S) (S "a" S "b") nil ("b")))))
+ (parser-generator--hash-to-list table-lr-items)))
+ (message "Passed LR-items with tokens as strings"))
+
+ (message "Passed LR-items for example 5.30 but with tokens as strings")
+
+ ;; TODO Test with look-ahead number > 1 he
+
+ (message "Passed tests for (parser-r--generate-goto-tables)"))
+
+ (defun parser-generator-lr-test--items-for-prefix ()
+ "Test `parser-generator-lr--items-for-prefix'."
+ (message "Starting tests for (parser-generator-lr--items-for-prefix)")
+
+ ;; Example 5.29 p 387
+ (parser-generator-set-grammar
+ '((Sp S) (a b) ((Sp S) (S (S a S b)) (S e)) Sp))
+ (parser-generator-set-look-ahead-number 1)
+ (parser-generator-process-grammar)
(should
(equal
- '((0 (((S) 1)))
- (1 ((("a") 2)))
- (2 (((S) 3)))
- (3 ((("a") 4) (("b") 5)))
- (4 (((S) 6)))
- (5 nil)
- (6 ((("a") 4) (("b") 7)))
- (7 nil))
- (parser-generator--hash-to-list parser-generator-lr--goto-tables)))
- (message "Passed GOTO-tables with tokens as strings")
+ '(((S) nil (S a S b) ($))
+ ((S) nil (S a S b) (a))
+ ((S) nil nil ($))
+ ((S) nil nil (a))
+ ((Sp) nil (S) ($)))
+ (parser-generator-lr--items-for-prefix 'e)))
+ (message "Passed V(e)")
(should
(equal
- '((0 (((S) nil (S "a" S "b") ("a")) ((S) nil (S "a" S "b") (e)) ((S) nil
nil ("a")) ((S) nil nil (e)) ((Sp) nil (S) (e))))
- (1 (((S) (S) ("a" S "b") ("a")) ((S) (S) ("a" S "b") (e)) ((Sp) (S)
nil (e))))
- (2 (((S) (S "a") (S "b") ("a")) ((S) (S "a") (S "b") (e)) ((S) nil (S
"a" S "b") ("a")) ((S) nil (S "a" S "b") ("b")) ((S) nil nil ("a")) ((S) nil
nil ("b"))))
- (3 (((S) (S) ("a" S "b") ("a")) ((S) (S) ("a" S "b") ("b")) ((S) (S
"a" S) ("b") ("a")) ((S) (S "a" S) ("b") (e))))
- (4 (((S) (S "a") (S "b") ("a")) ((S) (S "a") (S "b") ("b")) ((S) nil
(S "a" S "b") ("a")) ((S) nil (S "a" S "b") ("b")) ((S) nil nil ("a")) ((S) nil
nil ("b"))))
- (5 (((S) (S "a" S "b") nil ("a")) ((S) (S "a" S "b") nil (e))))
- (6 (((S) (S) ("a" S "b") ("a")) ((S) (S) ("a" S "b") ("b")) ((S) (S
"a" S) ("b") ("a")) ((S) (S "a" S) ("b") ("b"))))
- (7 (((S) (S "a" S "b") nil ("a")) ((S) (S "a" S "b") nil ("b")))))
- (parser-generator--hash-to-list table-lr-items)))
- (message "Passed LR-items with tokens as strings"))
-
- (message "Passed LR-items for example 5.30 but with tokens as strings")
-
- (message "Passed tests for (parser-r--generate-goto-tables)"))
-
-(defun parser-generator-lr-test--items-for-prefix ()
- "Test `parser-generator-lr--items-for-prefix'."
- (message "Starting tests for (parser-generator-lr--items-for-prefix)")
-
- ;; Example 5.29 p 387
- (parser-generator-set-grammar
- '((Sp S) (a b) ((Sp S) (S (S a S b)) (S e)) Sp))
- (parser-generator-set-look-ahead-number 1)
- (parser-generator-process-grammar)
-
- (should
- (equal
- '(((S) nil (S a S b) (a))
- ((S) nil (S a S b) (e))
- ((S) nil nil (a))
- ((S) nil nil (e))
- ((Sp) nil (S) (e)))
- (parser-generator-lr--items-for-prefix 'e)))
- (message "Passed V(e)")
-
- (should
- (equal
- '(((S) (S) (a S b) (a))
- ((S) (S) (a S b) (e))
- ((Sp) (S) nil (e)))
- (parser-generator-lr--items-for-prefix 'S)))
- (message "Passed V(S)")
-
- (should
- (equal
- nil
- (parser-generator-lr--items-for-prefix 'a)))
- (message "Passed V(a)")
+ '(((S) (S) (a S b) ($))
+ ((S) (S) (a S b) (a))
+ ((Sp) (S) nil ($)))
+ (parser-generator-lr--items-for-prefix 'S)))
+ (message "Passed V(S)")
- (should
- (equal
- nil
- (parser-generator-lr--items-for-prefix 'b)))
- (message "Passed V(b)")
-
- (should
- (equal
- '(((S) (S a) (S b) (a))
- ((S) (S a) (S b) (e))
- ((S) nil (S a S b) (a))
- ((S) nil (S a S b) (b))
- ((S) nil nil (a))
- ((S) nil nil (b)))
- (parser-generator-lr--items-for-prefix '(S a))))
- (message "Passed V(Sa)")
-
- (should
- (equal
- nil
- (parser-generator-lr--items-for-prefix '(S S))))
- (message "Passed V(SS)")
-
- (should
- (equal
- nil
- (parser-generator-lr--items-for-prefix '(S b))))
- (message "Passed V(Sb)")
-
- ;; a3 p. 390
- (should
- (equal
- '(((S) (S) (a S b) (a))
- ((S) (S) (a S b) (b))
- ((S) (S a S) (b) (a))
- ((S) (S a S) (b) (e)))
- (parser-generator-lr--items-for-prefix '(S a S))))
- (message "Passed V(SaS)")
-
- (should
- (equal
- nil
- (parser-generator-lr--items-for-prefix '(S a a))))
- (message "Passed V(Saa)")
-
- (should
- (equal
- nil
- (parser-generator-lr--items-for-prefix '(S a b))))
- (message "Passed V(Sab)")
-
- (message "Passed tests for (parser-generator-lr--items-for-prefix)"))
+ (should
+ (equal
+ nil
+ (parser-generator-lr--items-for-prefix 'a)))
+ (message "Passed V(a)")
-(defun parser-generator-lr-test--items-valid-p ()
- "Test `parser-generator-lr--items-valid-p'."
- (message "Started tests for (parser-generator-lr--items-valid-p)")
+ (should
+ (equal
+ nil
+ (parser-generator-lr--items-for-prefix 'b)))
+ (message "Passed V(b)")
- (parser-generator-set-grammar '((Sp S) (a b) ((Sp S) (S (S a S b)) (S e))
Sp))
- (parser-generator-set-look-ahead-number 1)
-
+ (should
+ (equal
+ '(((S) (S a) (S b) ($))
+ ((S) (S a) (S b) (a))
+ ((S) nil (S a S b) (a))
+ ((S) nil (S a S b) (b))
+ ((S) nil nil (a))
+ ((S) nil nil (b)))
+ (parser-generator-lr--items-for-prefix '(S a))))
+ (message "Passed V(Sa)")
- (let ((table-lr-items (parser-generator-process-grammar)))
+ (should
+ (equal
+ nil
+ (parser-generator-lr--items-for-prefix '(S S))))
+ (message "Passed V(SS)")
(should
(equal
- t
- (parser-generator-lr--items-valid-p
(parser-generator--hash-values-to-list table-lr-items t))))
+ nil
+ (parser-generator-lr--items-for-prefix '(S b))))
+ (message "Passed V(Sb)")
- (message "Passed first"))
+ ;; a3 p. 390
+ (should
+ (equal
+ '(((S) (S) (a S b) (a))
+ ((S) (S) (a S b) (b))
+ ((S) (S a S) (b) ($))
+ ((S) (S a S) (b) (a)))
+ (parser-generator-lr--items-for-prefix '(S a S))))
+ (message "Passed V(SaS)")
- (should
- (equal
- nil
- (parser-generator-lr--items-valid-p
- '(((S nil (S a S b) (a)) (S nil (S a S b) (e)) (S nil nil (a)) (S nil nil
(e)) (Sp nil (S) (e))) ((S (S) (a S b) (a)) (S (S) (a S b) (e)) (Sp (S) nil
(e))) ((S (S a) (S b) (a)) (S (S a) (S b) (e)) (S nil (S a S b) (a)) (S nil (S
a S b) (b)) (S nil nil (a)) (S nil nil (b))) ((S (S) (a S b) (a)) (S (S) (a S
b) (b)) (S (S a S) (b) (a)) (S (S a S) (b) (e))) ((S (S a S b) nil (a)) (S (S a
S b) (a) (a)) (S (S a S b) nil (e))) ((S (S a) (S b) (a)) (S (S a) (S b) (b))
(S nil (S a S b) (a)) [...]
+ (should
+ (equal
+ nil
+ (parser-generator-lr--items-for-prefix '(S a a))))
+ (message "Passed V(Saa)")
- (message "Passed tests for (parser-generator-lr--items-valid-p)"))
+ (should
+ (equal
+ nil
+ (parser-generator-lr--items-for-prefix '(S a b))))
+ (message "Passed V(Sab)")
-(defun parser-generator-lr-test-parse ()
- "Test `parser-generator-lr-parse'."
- (message "Started tests for (parser-generator-lr-parse)")
+ (message "Passed tests for (parser-generator-lr--items-for-prefix)"))
- (parser-generator-set-grammar
- '((Sp S) (a b) ((Sp S) (S (S a S b)) (S e)) Sp))
- (parser-generator-set-look-ahead-number 1)
- (parser-generator-process-grammar)
- (parser-generator-lr-generate-parser-tables)
- (setq
- parser-generator-lex-analyzer--function
- (lambda (index)
- (let* ((string '((a 1 . 2) (a 2 . 3) (b 3 . 4) (b 4 . 5)))
- (string-length (length string))
- (max-index index)
- (tokens))
- (while (and
- (< (1- index) string-length)
- (< (1- index) max-index))
- (push (nth (1- index) string) tokens)
- (setq index (1+ index)))
- (nreverse tokens))))
- (should
- (equal
- '(2 2 2 1 1)
- (parser-generator-lr-parse)))
- (message "Passed test with terminals as symbols")
-
- (setq
- parser-generator-lex-analyzer--function
- (lambda (index)
- (let* ((string '((a 1 . 2) (a 2 . 3) (b 3 . 4) (b 4 . 5) (b 5 . 6)))
- (string-length (length string))
- (max-index index)
- (tokens))
- (while (and
- (< (1- index) string-length)
- (< (1- index) max-index))
- (push (nth (1- index) string) tokens)
- (setq index (1+ index)))
- (nreverse tokens))))
- (should-error
- (parser-generator-lr--parse))
- (message "Passed test with terminals as symbols, invalid syntax")
-
- (parser-generator-set-grammar '((Sp S) ("a" "b") ((Sp S) (S (S "a" S "b"))
(S e)) Sp))
- (parser-generator-set-look-ahead-number 1)
- (parser-generator-process-grammar)
- (let ((lr-items (parser-generator-lr-generate-parser-tables)))
- (parser-generator--debug
- (message "lr-items: %s" (parser-generator--hash-values-to-list lr-items
t)))
- )
- (parser-generator--debug
- (message "goto-tables: %s" (parser-generator--hash-values-to-list
parser-generator-lr--goto-tables t))
- (message "action-tables: %s" (parser-generator--hash-values-to-list
parser-generator-lr--action-tables t)))
- (setq
- parser-generator-lex-analyzer--function
- (lambda (index)
- (let* ((string '(("a" 1 . 2) ("a" 2 . 3) ("b" 3 . 4) ("b" 4 . 5)))
- (string-length (length string))
- (max-index index)
- (tokens))
- (while (and
- (< (1- index) string-length)
- (< (1- index) max-index))
- (push (nth (1- index) string) tokens)
- (setq index (1+ index)))
- (nreverse tokens))))
- (should
- (equal
- '(2 2 2 1 1)
- (parser-generator-lr-parse)))
- (message "Passed test with terminals as string")
-
- (setq
- parser-generator-lex-analyzer--function
- (lambda (index)
- (let* ((string '(("a" 1 . 2) ("a" 2 . 3) ("b" 3 . 4) ("b" 4 . 5) ("b" 5 .
6)))
- (string-length (length string))
- (max-index index)
- (tokens))
- (while (and
- (< (1- index) string-length)
- (< (1- index) max-index))
- (push (nth (1- index) string) tokens)
- (setq index (1+ index)))
- (nreverse tokens))))
- (should-error
- (parser-generator-lr--parse))
- (message "Passed test with terminals as string, invalid syntax")
-
- (setq
- parser-generator-lex-analyzer--function
- (lambda (index)
- (let* ((string '(("a" 1 . 2) ("a" 2 . 3) ("b" 3 . 4) ("b" 4 . 5)))
- (string-length (length string))
- (max-index index)
- (tokens))
- (while (and
- (< (1- index) string-length)
- (< (1- index) max-index))
- (push (nth (1- index) string) tokens)
- (setq index (1+ index)))
- (nreverse tokens))))
-
- (parser-generator-lr-test--parse-incremental-vs-regular)
- (message "Passed incremental-tests")
-
- (message "Passed tests for (parser-generator-lr--parse)"))
-
-(defun parser-generator-lr-test-parse-k-2 ()
- "Test `parser-generator-lr-parse' with k = 2."
- (message "Started tests for (parser-generator-lr-parse) k = 2")
-
- (parser-generator-set-grammar '((Sp S) ("a" "b") ((Sp S) (S (S "a" S "b"))
(S e)) Sp))
- (parser-generator-set-look-ahead-number 2)
- (parser-generator-process-grammar)
+ (defun parser-generator-lr-test--items-valid-p ()
+ "Test `parser-generator-lr--items-valid-p'."
+ (message "Started tests for (parser-generator-lr--items-valid-p)")
- (let ((lr-items (parser-generator-lr--generate-goto-tables)))
- (parser-generator--debug
- (message "all lr-items: %s" (parser-generator--hash-values-to-list
lr-items t)))
-
- ;; (should
- ;; (equal
- ;; '((0 ((S 1)))
- ;; (1 (("a" 2)))
- ;; (2 ((S 3)))
- ;; (3 (("a" 4) ("b" 5)))
- ;; (4 ((S 6)))
- ;; (5 nil)
- ;; (6 (("a" 4) ("b" 7)))
- ;; (7 nil))
- ;; (parser-generator--hash-to-list
- ;; parser-generator-lr--goto-tables)))
- ;; (message "Passed GOTO-tables k = 2")
-
- ;; TODO Validate lr-items here
-
- ;; (should
- ;; (equal
- ;; '((0 (((S) nil (S "a" S "b") ("a" e)) ((S) nil (S "a" S "b") ("a"
"a")) ((S) nil (S "a" S "b") (e e)) ((S) nil nil ("a" e)) ((S) nil nil ("a"
"a")) ((S) nil nil (e e)) ((Sp) nil (S) (e e))))
- ;; (1 (((S) (S) ("a" S "b") ("a" "a")) ((S) (S) ("a" S "b") ("a" e))
((S) (S) ("a" S "b") (e e)) ((Sp) (S) nil (e e))))
- ;; (2 (((S) (S "a") (S "b") ("a" e)) ((S) (S "a") (S "b") ("a" "a"))
((S) (S "a") (S "b") (e e)) ((S) nil (S "a" S "b") ("a" e)) ((S) nil (S "a" S
"b") ("a" "a")) ((S) nil (S "a" S "b") ("b" e)) ((S) nil nil ("a" e)) ((S) nil
nil ("a" "a")) ((S) nil nil ("b" e))))
- ;; (3 (((S) (S) ("a" S "b") ("a" "a")) ((S) (S) ("a" S "b") ("a" e))
((S) (S) ("a" S "b") ("b" e)) ((S) (S "a" S) ("b") ("a" "a")) ((S) (S "a" S)
("b") ("a" e)) ((S) (S "a" S) ("b") (e e))))
- ;; (4 (((S) (S "a") (S "b") ("a" e)) ((S) (S "a") (S "b") ("a" "a"))
((S) (S "a") (S "b") ("b" e)) ((S) nil (S "a" S "b") ("a" e)) ((S) nil (S "a" S
"b") ("a" "a")) ((S) nil (S "a" S "b") ("b" e)) ((S) nil nil ("a" e)) ((S) nil
nil ("a" "a")) ((S) nil nil ("b" e))))
- ;; (5 (((S) (S "a" S "b") nil ("a" e)) ((S) (S "a" S "b") nil ("a"
"a")) ((S) (S "a" S "b") nil (e e))))
- ;; (6 (((S) (S) ("a" S "b") ("a" "a")) ((S) (S) ("a" S "b") ("a" e))
((S) (S) ("a" S "b") ("b" e)) ((S) (S "a" S) ("b") ("a" "a")) ((S) (S "a" S)
("b") ("a" e)) ((S) (S "a" S) ("b") ("b" e))))
- ;; (7 (((S) (S "a" S "b") nil ("a" e)) ((S) (S "a" S "b") nil ("a"
"a")) ((S) (S "a" S "b") nil ("b" e)))))
- ;; (parser-generator--hash-to-list
- ;; lr-items)))
- ;; (message "Passed LR-items k = 2")
-
- (parser-generator-lr--generate-action-tables lr-items)
- (parser-generator--debug
- (message "action-tables: %s" (parser-generator--hash-values-to-list
parser-generator-lr--action-tables t)))
+ (parser-generator-set-grammar '((Sp S) (a b) ((Sp S) (S (S a S b)) (S e))
Sp))
+ (parser-generator-set-look-ahead-number 1)
+
- ;; TODO Validate action-table here, should be able to reduce at look-ahead
("a" "b") as well
-
- ;; (should
- ;; (equal
- ;; '((0 ((("a" "a") reduce 2) (("a" e) reduce 2) ((e e) reduce 2)))
- ;; (1 ((("a" "b") shift) ((e e) accept)))
- ;; (2 ((("a" "a") reduce 2) (("a" e) reduce 2) (("b" e) reduce 2)))
- ;; (3 ((("a" "b") shift) (("b" e) shift) (("b" "a") shift)))
- ;; (4 ((("a" "a") reduce 2) (("a" e) reduce 2) (("b" e) reduce 2)))
- ;; (5 ((("a" "a") reduce 1) (("a" e) reduce 1) ((e e) reduce 1)))
- ;; (6 ((("a" "b") shift) (("b" "b") shift) (("b" "a") shift)))
- ;; (7 ((("a" "a") reduce 1) (("a" e) reduce 1) (("b" e) reduce 1))))
- ;; (parser-generator--hash-to-list
- ;; parser-generator-lr--action-tables)))
- ;; (message "Passed ACTION-tables k = 2")
+ (let ((table-lr-items (parser-generator-process-grammar)))
- )
- (setq
- parser-generator-lex-analyzer--function
- (lambda (index)
- (let* ((string '(("a" 1 . 2) ("b" 2 . 3)))
- (string-length (length string))
- (max-index index)
- (tokens))
- (while (and
- (< (1- index) string-length)
- (< (1- index) max-index))
- (push (nth (1- index) string) tokens)
- (setq index (1+ index)))
- (nreverse tokens))))
- (should
- (equal
- '(2 2 2 1 1)
- (parser-generator-lr-parse)))
- (message "Passed test with terminals as string with look-ahead-number 2")
+ (should
+ (equal
+ t
+ (parser-generator-lr--items-valid-p
(parser-generator--hash-values-to-list table-lr-items t))))
- (message "Passed tests for (parser-generator-lr--parse-k-2)"))
+ (message "Passed first"))
-(defun parser-generator-lr-test-translate ()
- "Test `parser-generator-lr-translate'."
- (message "Started tests for (parser-generator-lr-translate)")
+ (should
+ (equal
+ nil
+ (parser-generator-lr--items-valid-p
+ '(((S nil (S a S b) (a)) (S nil (S a S b) (e)) (S nil nil (a)) (S nil
nil (e)) (Sp nil (S) (e))) ((S (S) (a S b) (a)) (S (S) (a S b) (e)) (Sp (S) nil
(e))) ((S (S a) (S b) (a)) (S (S a) (S b) (e)) (S nil (S a S b) (a)) (S nil (S
a S b) (b)) (S nil nil (a)) (S nil nil (b))) ((S (S) (a S b) (a)) (S (S) (a S
b) (b)) (S (S a S) (b) (a)) (S (S a S) (b) (e))) ((S (S a S b) nil (a)) (S (S a
S b) (a) (a)) (S (S a S b) nil (e))) ((S (S a) (S b) (a)) (S (S a) (S b) (b))
(S nil (S a S b) (a) [...]
- ;; Test translation with terminals as strings here
+ (message "Passed tests for (parser-generator-lr--items-valid-p)"))
- (let ((buffer (generate-new-buffer "*a*")))
- (switch-to-buffer buffer)
- (insert "aabb")
+ (defun parser-generator-lr-test-parse ()
+ "Test `parser-generator-lr-parse'."
+ (message "Started tests for (parser-generator-lr-parse)")
- (parser-generator-set-grammar '((Sp S) ("a" "b") ((Sp S) (S (S "a" S "b"
(lambda(args) (let ((list "")) (dolist (item args) (when item (setq list
(format "%s%s" item list)))) list)))) (S e)) Sp))
+ (parser-generator-set-grammar
+ '((Sp S) (a b) ((Sp S) (S (S a S b)) (S e)) Sp))
(parser-generator-set-look-ahead-number 1)
(parser-generator-process-grammar)
(parser-generator-lr-generate-parser-tables)
-
(setq
parser-generator-lex-analyzer--function
(lambda (index)
- (with-current-buffer buffer
- (when (<= (+ index 1) (point-max))
- (let ((start index)
- (end (+ index 1)))
- (let ((token (buffer-substring-no-properties start end)))
- `(,token ,start . ,end)))))))
-
- (setq
- parser-generator-lex-analyzer--get-function
- (lambda (token)
- (with-current-buffer buffer
- (let ((start (car (cdr token)))
- (end (cdr (cdr token))))
- (when (<= end (point-max))
- (buffer-substring-no-properties start end))))))
-
+ (let* ((string '((a 1 . 2) (a 2 . 3) (b 3 . 4) (b 4 . 5)))
+ (string-length (length string))
+ (max-index index)
+ (tokens))
+ (while (and
+ (< (1- index) string-length)
+ (< (1- index) max-index))
+ (push (nth (1- index) string) tokens)
+ (setq index (1+ index)))
+ (nreverse tokens))))
(should
(equal
- "bbaaba"
- (parser-generator-lr-translate)))
-
- (kill-buffer buffer))
- (message "Passed test with translation 1")
-
- (let ((buffer (generate-new-buffer "*a*")))
- (switch-to-buffer buffer)
- (insert "if (a) { b; }")
-
- (parser-generator-set-grammar '((Sp S) (";" OPEN_ROUND_BRACKET
CLOSE_ROUND_BRACKET ECHO IF OPEN_CURLY_BRACKET CLOSE_CURLY_BRACKET VARIABLE)
((Sp S) (S (IF OPEN_ROUND_BRACKET VARIABLE CLOSE_ROUND_BRACKET
OPEN_CURLY_BRACKET VARIABLE ";" CLOSE_CURLY_BRACKET (lambda(args) (format
"(when %s %s)" (nth 2 args) (nth 5 args)))))) Sp))
- (parser-generator-set-look-ahead-number 1)
- (parser-generator-process-grammar)
- (parser-generator-lr-generate-parser-tables)
+ '(2 2 2 1 1)
+ (parser-generator-lr-parse)))
+ (message "Passed test with terminals as symbols")
(setq
parser-generator-lex-analyzer--function
(lambda (index)
- (with-current-buffer buffer
- (unless (>= index (point-max))
- (goto-char index)
- (unless (looking-at "[^ \n\t]")
- (search-forward-regexp "[^ \n\t]" nil t nil)
- (forward-char -1))
- (let ((token))
- (cond
- ((looking-at "if")
- (setq token `(IF ,(match-beginning 0) . ,(match-end 0))))
- ((looking-at "echo")
- (setq token `(ECHO ,(match-beginning 0) . ,(match-end 0))))
- ((looking-at "(")
- (setq token `(OPEN_ROUND_BRACKET ,(match-beginning 0) .
,(match-end 0))))
- ((looking-at ")")
- (setq token `(CLOSE_ROUND_BRACKET ,(match-beginning 0) .
,(match-end 0))))
- ((looking-at "{")
- (setq token `(OPEN_CURLY_BRACKET ,(match-beginning 0) .
,(match-end 0))))
- ((looking-at "}")
- (setq token `(CLOSE_CURLY_BRACKET ,(match-beginning 0) .
,(match-end 0))))
- ((looking-at ";")
- (setq token `(";" ,(match-beginning 0) . ,(match-end 0))))
- ((looking-at "[a-zA-Z]+")
- (setq token `(VARIABLE ,(match-beginning 0) . ,(match-end 0))))
- (t (error "Invalid syntax! Could not lex-analyze at %s!"
(point))))
- token)))))
-
- (setq
- parser-generator-lex-analyzer--get-function
- (lambda (token)
- (with-current-buffer buffer
- (let ((start (car (cdr token)))
- (end (cdr (cdr token))))
- (when (<= end (point-max))
- (buffer-substring-no-properties start end))))))
-
- (should
- (equal
- "(when a b)"
- (parser-generator-lr-translate)))
- (message "Passed test with non-nested translation")
-
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
+ (let* ((string '((a 1 . 2) (a 2 . 3) (b 3 . 4) (b 4 . 5) (b 5 . 6)))
+ (string-length (length string))
+ (max-index index)
+ (tokens))
+ (while (and
+ (< (1- index) string-length)
+ (< (1- index) max-index))
+ (push (nth (1- index) string) tokens)
+ (setq index (1+ index)))
+ (nreverse tokens))))
+ (should-error
+ (parser-generator-lr--parse))
+ (message "Passed test with terminals as symbols, invalid syntax")
- (parser-generator-set-grammar '((Sp S T) (";" OPEN_ROUND_BRACKET
CLOSE_ROUND_BRACKET ECHO IF OPEN_CURLY_BRACKET CLOSE_CURLY_BRACKET VARIABLE)
((Sp S) (S (IF OPEN_ROUND_BRACKET VARIABLE CLOSE_ROUND_BRACKET
OPEN_CURLY_BRACKET T CLOSE_CURLY_BRACKET (lambda(args) (format "(when %s %s)"
(nth 2 args) (nth 5 args))))) (T (ECHO VARIABLE ";" (lambda(args) (format
"(message %s)" (nth 1 args)))) (VARIABLE ";" (lambda(args) (format "%s" (nth 0
args)))))) Sp))
+ (parser-generator-set-grammar '((Sp S) ("a" "b") ((Sp S) (S (S "a" S "b"))
(S e)) Sp))
(parser-generator-set-look-ahead-number 1)
(parser-generator-process-grammar)
- (parser-generator-lr-generate-parser-tables)
-
- (insert "if (a) { echo b; }")
-
+ (let ((lr-items (parser-generator-lr-generate-parser-tables)))
+ (parser-generator--debug
+ (message "lr-items: %s" (parser-generator--hash-values-to-list lr-items
t)))
+ )
+ (parser-generator--debug
+ (message "goto-tables: %s" (parser-generator--hash-values-to-list
parser-generator-lr--goto-tables t))
+ (message "action-tables: %s" (parser-generator--hash-values-to-list
parser-generator-lr--action-tables t)))
+ (setq
+ parser-generator-lex-analyzer--function
+ (lambda (index)
+ (let* ((string '(("a" 1 . 2) ("a" 2 . 3) ("b" 3 . 4) ("b" 4 . 5)))
+ (string-length (length string))
+ (max-index index)
+ (tokens))
+ (while (and
+ (< (1- index) string-length)
+ (< (1- index) max-index))
+ (push (nth (1- index) string) tokens)
+ (setq index (1+ index)))
+ (nreverse tokens))))
(should
(equal
- "(when a (message b))"
- (parser-generator-lr-translate)))
-
- (message "Passed test with nested-translation with depth 2")
-
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
- (goto-char 1)
- (insert "if (a) { echo b }")
-
- (should-error
- (parser-generator-lr-parse))
-
- (kill-buffer buffer))
- (message "Passed test with translation 2")
-
- (let ((buffer (generate-new-buffer "*a*")))
- (switch-to-buffer buffer)
- (insert "if (a) { b; }")
-
- (parser-generator-set-grammar '((Sp S) (";" OPEN_ROUND_BRACKET
CLOSE_ROUND_BRACKET IF OPEN_CURLY_BRACKET CLOSE_CURLY_BRACKET VARIABLE) ((Sp S)
(S (IF OPEN_ROUND_BRACKET VARIABLE CLOSE_ROUND_BRACKET OPEN_CURLY_BRACKET
VARIABLE ";" CLOSE_CURLY_BRACKET (lambda(args) (format "(when %s %s)" (nth 2
args) (nth 5 args)))))) Sp))
- (parser-generator-set-look-ahead-number 1)
- (parser-generator-process-grammar)
- (parser-generator-lr-generate-parser-tables)
+ '(2 2 2 1 1)
+ (parser-generator-lr-parse)))
+ (message "Passed test with terminals as string")
(setq
parser-generator-lex-analyzer--function
(lambda (index)
- (with-current-buffer "*a*"
- (unless (>= index (point-max))
- (goto-char index)
- (unless (looking-at "[^ \n\t]")
- (search-forward-regexp "[^ \n\t]" nil t nil)
- (forward-char -1))
- (let ((token))
- (cond
- ((looking-at "if")
- (setq token `(IF ,(match-beginning 0) . ,(match-end 0))))
- ((looking-at "(")
- (setq token `(OPEN_ROUND_BRACKET ,(match-beginning 0) .
,(match-end 0))))
- ((looking-at ")")
- (setq token `(CLOSE_ROUND_BRACKET ,(match-beginning 0) .
,(match-end 0))))
- ((looking-at "{")
- (setq token `(OPEN_CURLY_BRACKET ,(match-beginning 0) .
,(match-end 0))))
- ((looking-at "}")
- (setq token `(CLOSE_CURLY_BRACKET ,(match-beginning 0) .
,(match-end 0))))
- ((looking-at ";")
- (setq token `(";" ,(match-beginning 0) . ,(match-end 0))))
- ((looking-at "[a-zA-Z]+")
- (setq token `(VARIABLE ,(match-beginning 0) . ,(match-end 0))))
- (t (error "Invalid syntax! Could not lex-analyze at %s!"
(point))))
- token)))))
+ (let* ((string '(("a" 1 . 2) ("a" 2 . 3) ("b" 3 . 4) ("b" 4 . 5) ("b" 5
. 6)))
+ (string-length (length string))
+ (max-index index)
+ (tokens))
+ (while (and
+ (< (1- index) string-length)
+ (< (1- index) max-index))
+ (push (nth (1- index) string) tokens)
+ (setq index (1+ index)))
+ (nreverse tokens))))
+ (should-error
+ (parser-generator-lr--parse))
+ (message "Passed test with terminals as string, invalid syntax")
(setq
- parser-generator-lex-analyzer--get-function
- (lambda (token)
- (with-current-buffer "*a*"
- (let ((start (car (cdr token)))
- (end (cdr (cdr token))))
- (when (<= end (point-max))
- (buffer-substring-no-properties start end))))))
+ parser-generator-lex-analyzer--function
+ (lambda (index)
+ (let* ((string '(("a" 1 . 2) ("a" 2 . 3) ("b" 3 . 4) ("b" 4 . 5)))
+ (string-length (length string))
+ (max-index index)
+ (tokens))
+ (while (and
+ (< (1- index) string-length)
+ (< (1- index) max-index))
+ (push (nth (1- index) string) tokens)
+ (setq index (1+ index)))
+ (nreverse tokens))))
(parser-generator-lr-test--parse-incremental-vs-regular)
- (kill-buffer buffer))
+ (message "Passed incremental-tests")
- (message "Passed incremental tests")
+ (message "Passed tests for (parser-generator-lr--parse)"))
- (message "Passed tests for (parser-generator-lr-translate)"))
+ (defun parser-generator-lr-test-parse-k-2 ()
+ "Test `parser-generator-lr-parse' with k = 2."
+ (message "Started tests for (parser-generator-lr-parse) k = 2")
-(defun parser-generator-lr-test ()
- "Run test."
- ;; (setq debug-on-error t)
+ (parser-generator-set-grammar '((Sp S) ("a" "b") ((Sp S) (S (S "a" S "b"))
(S e)) Sp))
+ (parser-generator-set-look-ahead-number 2)
+ (parser-generator-process-grammar)
- (parser-generator-lr-test--items-for-prefix)
- (parser-generator-lr-test--items-valid-p)
- (parser-generator-lr-test--generate-goto-tables)
- (parser-generator-lr-test--generate-action-tables)
- (parser-generator-lr-test-parse)
- (parser-generator-lr-test-translate)
- ;; (parser-generator-lr-test-parse-k-2)
- )
+ (let ((lr-items (parser-generator-lr--generate-goto-tables)))
+ (parser-generator--debug
+ (message "all lr-items: %s" (parser-generator--hash-values-to-list
lr-items t)))
+
+ ;; (should
+ ;; (equal
+ ;; '((0 ((S 1)))
+ ;; (1 (("a" 2)))
+ ;; (2 ((S 3)))
+ ;; (3 (("a" 4) ("b" 5)))
+ ;; (4 ((S 6)))
+ ;; (5 nil)
+ ;; (6 (("a" 4) ("b" 7)))
+ ;; (7 nil))
+ ;; (parser-generator--hash-to-list
+ ;; parser-generator-lr--goto-tables)))
+ ;; (message "Passed GOTO-tables k = 2")
+
+ ;; TODO Validate lr-items here
+
+ ;; (should
+ ;; (equal
+ ;; '((0 (((S) nil (S "a" S "b") ("a" e)) ((S) nil (S "a" S "b") ("a"
"a")) ((S) nil (S "a" S "b") (e e)) ((S) nil nil ("a" e)) ((S) nil nil ("a"
"a")) ((S) nil nil (e e)) ((Sp) nil (S) (e e))))
+ ;; (1 (((S) (S) ("a" S "b") ("a" "a")) ((S) (S) ("a" S "b") ("a" e))
((S) (S) ("a" S "b") (e e)) ((Sp) (S) nil (e e))))
+ ;; (2 (((S) (S "a") (S "b") ("a" e)) ((S) (S "a") (S "b") ("a" "a"))
((S) (S "a") (S "b") (e e)) ((S) nil (S "a" S "b") ("a" e)) ((S) nil (S "a" S
"b") ("a" "a")) ((S) nil (S "a" S "b") ("b" e)) ((S) nil nil ("a" e)) ((S) nil
nil ("a" "a")) ((S) nil nil ("b" e))))
+ ;; (3 (((S) (S) ("a" S "b") ("a" "a")) ((S) (S) ("a" S "b") ("a" e))
((S) (S) ("a" S "b") ("b" e)) ((S) (S "a" S) ("b") ("a" "a")) ((S) (S "a" S)
("b") ("a" e)) ((S) (S "a" S) ("b") (e e))))
+ ;; (4 (((S) (S "a") (S "b") ("a" e)) ((S) (S "a") (S "b") ("a" "a"))
((S) (S "a") (S "b") ("b" e)) ((S) nil (S "a" S "b") ("a" e)) ((S) nil (S "a" S
"b") ("a" "a")) ((S) nil (S "a" S "b") ("b" e)) ((S) nil nil ("a" e)) ((S) nil
nil ("a" "a")) ((S) nil nil ("b" e))))
+ ;; (5 (((S) (S "a" S "b") nil ("a" e)) ((S) (S "a" S "b") nil ("a"
"a")) ((S) (S "a" S "b") nil (e e))))
+ ;; (6 (((S) (S) ("a" S "b") ("a" "a")) ((S) (S) ("a" S "b") ("a" e))
((S) (S) ("a" S "b") ("b" e)) ((S) (S "a" S) ("b") ("a" "a")) ((S) (S "a" S)
("b") ("a" e)) ((S) (S "a" S) ("b") ("b" e))))
+ ;; (7 (((S) (S "a" S "b") nil ("a" e)) ((S) (S "a" S "b") nil ("a"
"a")) ((S) (S "a" S "b") nil ("b" e)))))
+ ;; (parser-generator--hash-to-list
+ ;; lr-items)))
+ ;; (message "Passed LR-items k = 2")
+
+ (parser-generator-lr--generate-action-tables lr-items)
+ (parser-generator--debug
+ (message "action-tables: %s" (parser-generator--hash-values-to-list
parser-generator-lr--action-tables t)))
+
+ ;; TODO Validate action-table here, should be able to reduce at
look-ahead ("a" "b") as well
+
+ ;; (should
+ ;; (equal
+ ;; '((0 ((("a" "a") reduce 2) (("a" e) reduce 2) ((e e) reduce 2)))
+ ;; (1 ((("a" "b") shift) ((e e) accept)))
+ ;; (2 ((("a" "a") reduce 2) (("a" e) reduce 2) (("b" e) reduce 2)))
+ ;; (3 ((("a" "b") shift) (("b" e) shift) (("b" "a") shift)))
+ ;; (4 ((("a" "a") reduce 2) (("a" e) reduce 2) (("b" e) reduce 2)))
+ ;; (5 ((("a" "a") reduce 1) (("a" e) reduce 1) ((e e) reduce 1)))
+ ;; (6 ((("a" "b") shift) (("b" "b") shift) (("b" "a") shift)))
+ ;; (7 ((("a" "a") reduce 1) (("a" e) reduce 1) (("b" e) reduce 1))))
+ ;; (parser-generator--hash-to-list
+ ;; parser-generator-lr--action-tables)))
+ ;; (message "Passed ACTION-tables k = 2")
+
+ )
+ (setq
+ parser-generator-lex-analyzer--function
+ (lambda (index)
+ (let* ((string '(("a" 1 . 2) ("b" 2 . 3)))
+ (string-length (length string))
+ (max-index index)
+ (tokens))
+ (while (and
+ (< (1- index) string-length)
+ (< (1- index) max-index))
+ (push (nth (1- index) string) tokens)
+ (setq index (1+ index)))
+ (nreverse tokens))))
+ (should
+ (equal
+ '(2 2 2 1 1)
+ (parser-generator-lr-parse)))
+ (message "Passed test with terminals as string with look-ahead-number 2")
+
+ (message "Passed tests for (parser-generator-lr--parse-k-2)"))
+
+ (defun parser-generator-lr-test-translate ()
+ "Test `parser-generator-lr-translate'."
+ (message "Started tests for (parser-generator-lr-translate)")
+
+ ;; Test translation with terminals as strings here
+
+ (let ((buffer (generate-new-buffer "*a*")))
+ (switch-to-buffer buffer)
+ (insert "aabb")
+
+ (parser-generator-set-grammar '((Sp S) ("a" "b") ((Sp S) (S (S "a" S "b"
(lambda(args) (let ((list "")) (dolist (item args) (when item (setq list
(format "%s%s" item list)))) list)))) (S e)) Sp))
+ (parser-generator-set-look-ahead-number 1)
+ (parser-generator-process-grammar)
+ (parser-generator-lr-generate-parser-tables)
+
+ (setq
+ parser-generator-lex-analyzer--function
+ (lambda (index)
+ (with-current-buffer buffer
+ (when (<= (+ index 1) (point-max))
+ (let ((start index)
+ (end (+ index 1)))
+ (let ((token (buffer-substring-no-properties start end)))
+ `(,token ,start . ,end)))))))
+
+ (setq
+ parser-generator-lex-analyzer--get-function
+ (lambda (token)
+ (with-current-buffer buffer
+ (let ((start (car (cdr token)))
+ (end (cdr (cdr token))))
+ (when (<= end (point-max))
+ (buffer-substring-no-properties start end))))))
+
+ (should
+ (equal
+ "bbaaba"
+ (parser-generator-lr-translate)))
+
+ (kill-buffer buffer))
+ (message "Passed test with translation 1")
+
+ (let ((buffer (generate-new-buffer "*a*")))
+ (switch-to-buffer buffer)
+ (insert "if (a) { b; }")
+
+ (parser-generator-set-grammar '((Sp S) (";" OPEN_ROUND_BRACKET
CLOSE_ROUND_BRACKET ECHO IF OPEN_CURLY_BRACKET CLOSE_CURLY_BRACKET VARIABLE)
((Sp S) (S (IF OPEN_ROUND_BRACKET VARIABLE CLOSE_ROUND_BRACKET
OPEN_CURLY_BRACKET VARIABLE ";" CLOSE_CURLY_BRACKET (lambda(args) (format
"(when %s %s)" (nth 2 args) (nth 5 args)))))) Sp))
+ (parser-generator-set-look-ahead-number 1)
+ (parser-generator-process-grammar)
+ (parser-generator-lr-generate-parser-tables)
+
+ (setq
+ parser-generator-lex-analyzer--function
+ (lambda (index)
+ (with-current-buffer buffer
+ (unless (>= index (point-max))
+ (goto-char index)
+ (unless (looking-at "[^ \n\t]")
+ (search-forward-regexp "[^ \n\t]" nil t nil)
+ (forward-char -1))
+ (let ((token))
+ (cond
+ ((looking-at "if")
+ (setq token `(IF ,(match-beginning 0) . ,(match-end 0))))
+ ((looking-at "echo")
+ (setq token `(ECHO ,(match-beginning 0) . ,(match-end 0))))
+ ((looking-at "(")
+ (setq token `(OPEN_ROUND_BRACKET ,(match-beginning 0) .
,(match-end 0))))
+ ((looking-at ")")
+ (setq token `(CLOSE_ROUND_BRACKET ,(match-beginning 0) .
,(match-end 0))))
+ ((looking-at "{")
+ (setq token `(OPEN_CURLY_BRACKET ,(match-beginning 0) .
,(match-end 0))))
+ ((looking-at "}")
+ (setq token `(CLOSE_CURLY_BRACKET ,(match-beginning 0) .
,(match-end 0))))
+ ((looking-at ";")
+ (setq token `(";" ,(match-beginning 0) . ,(match-end 0))))
+ ((looking-at "[a-zA-Z]+")
+ (setq token `(VARIABLE ,(match-beginning 0) . ,(match-end
0))))
+ (t (error "Invalid syntax! Could not lex-analyze at %s!"
(point))))
+ token)))))
+
+ (setq
+ parser-generator-lex-analyzer--get-function
+ (lambda (token)
+ (with-current-buffer buffer
+ (let ((start (car (cdr token)))
+ (end (cdr (cdr token))))
+ (when (<= end (point-max))
+ (buffer-substring-no-properties start end))))))
+
+ (should
+ (equal
+ "(when a b)"
+ (parser-generator-lr-translate)))
+ (message "Passed test with non-nested translation")
+
+ (switch-to-buffer buffer)
+ (kill-region (point-min) (point-max))
+
+ (parser-generator-set-grammar '((Sp S T) (";" OPEN_ROUND_BRACKET
CLOSE_ROUND_BRACKET ECHO IF OPEN_CURLY_BRACKET CLOSE_CURLY_BRACKET VARIABLE)
((Sp S) (S (IF OPEN_ROUND_BRACKET VARIABLE CLOSE_ROUND_BRACKET
OPEN_CURLY_BRACKET T CLOSE_CURLY_BRACKET (lambda(args) (format "(when %s %s)"
(nth 2 args) (nth 5 args))))) (T (ECHO VARIABLE ";" (lambda(args) (format
"(message %s)" (nth 1 args)))) (VARIABLE ";" (lambda(args) (format "%s" (nth 0
args)))))) Sp))
+ (parser-generator-set-look-ahead-number 1)
+ (parser-generator-process-grammar)
+ (parser-generator-lr-generate-parser-tables)
+
+ (insert "if (a) { echo b; }")
+
+ (should
+ (equal
+ "(when a (message b))"
+ (parser-generator-lr-translate)))
+
+ (message "Passed test with nested-translation with depth 2")
+
+ (switch-to-buffer buffer)
+ (kill-region (point-min) (point-max))
+ (goto-char 1)
+ (insert "if (a) { echo b }")
+
+ (should-error
+ (parser-generator-lr-parse))
+
+ (kill-buffer buffer))
+ (message "Passed test with translation 2")
+
+ (let ((buffer (generate-new-buffer "*a*")))
+ (switch-to-buffer buffer)
+ (insert "if (a) { b; }")
+
+ (parser-generator-set-grammar '((Sp S) (";" OPEN_ROUND_BRACKET
CLOSE_ROUND_BRACKET IF OPEN_CURLY_BRACKET CLOSE_CURLY_BRACKET VARIABLE) ((Sp S)
(S (IF OPEN_ROUND_BRACKET VARIABLE CLOSE_ROUND_BRACKET OPEN_CURLY_BRACKET
VARIABLE ";" CLOSE_CURLY_BRACKET (lambda(args) (format "(when %s %s)" (nth 2
args) (nth 5 args)))))) Sp))
+ (parser-generator-set-look-ahead-number 1)
+ (parser-generator-process-grammar)
+ (parser-generator-lr-generate-parser-tables)
+
+ (setq
+ parser-generator-lex-analyzer--function
+ (lambda (index)
+ (with-current-buffer "*a*"
+ (unless (>= index (point-max))
+ (goto-char index)
+ (unless (looking-at "[^ \n\t]")
+ (search-forward-regexp "[^ \n\t]" nil t nil)
+ (forward-char -1))
+ (let ((token))
+ (cond
+ ((looking-at "if")
+ (setq token `(IF ,(match-beginning 0) . ,(match-end 0))))
+ ((looking-at "(")
+ (setq token `(OPEN_ROUND_BRACKET ,(match-beginning 0) .
,(match-end 0))))
+ ((looking-at ")")
+ (setq token `(CLOSE_ROUND_BRACKET ,(match-beginning 0) .
,(match-end 0))))
+ ((looking-at "{")
+ (setq token `(OPEN_CURLY_BRACKET ,(match-beginning 0) .
,(match-end 0))))
+ ((looking-at "}")
+ (setq token `(CLOSE_CURLY_BRACKET ,(match-beginning 0) .
,(match-end 0))))
+ ((looking-at ";")
+ (setq token `(";" ,(match-beginning 0) . ,(match-end 0))))
+ ((looking-at "[a-zA-Z]+")
+ (setq token `(VARIABLE ,(match-beginning 0) . ,(match-end
0))))
+ (t (error "Invalid syntax! Could not lex-analyze at %s!"
(point))))
+ token)))))
+
+ (setq
+ parser-generator-lex-analyzer--get-function
+ (lambda (token)
+ (with-current-buffer "*a*"
+ (let ((start (car (cdr token)))
+ (end (cdr (cdr token))))
+ (when (<= end (point-max))
+ (buffer-substring-no-properties start end))))))
+
+ (parser-generator-lr-test--parse-incremental-vs-regular)
+ (kill-buffer buffer))
+
+ (message "Passed incremental tests")
+
+ (message "Passed tests for (parser-generator-lr-translate)"))
+
+ (defun parser-generator-lr-test ()
+ "Run test."
+ ;; (setq debug-on-error t)
+
+ (parser-generator-lr-test--items-for-prefix)
+ (parser-generator-lr-test--items-valid-p)
+ (parser-generator-lr-test--generate-goto-tables)
+ (parser-generator-lr-test--generate-action-tables)
+ (parser-generator-lr-test-parse)
+ (parser-generator-lr-test-translate)
+ ;; (parser-generator-lr-test-parse-k-2)
+ )
-(provide 'parser-generator-lr-test)
+ (provide 'parser-generator-lr-test)
;;; parser-generator-lr-test.el ends here
diff --git a/test/parser-generator-test.el b/test/parser-generator-test.el
index f8b24c3..7ee76af 100644
--- a/test/parser-generator-test.el
+++ b/test/parser-generator-test.el
@@ -49,12 +49,10 @@
(should
(equal
t
- (parser-generator--valid-look-ahead-p 'e)))
+ (parser-generator--valid-look-ahead-p '$)))
(message "Passed with look-ahead number is 1")
- ;; TODO Test with look-ahead number = 2 here
-
(parser-generator-set-look-ahead-number 2)
(parser-generator-set-grammar '((S A) ("a" "b") ((S A) (A ("b" "a"))) S))
(parser-generator-process-grammar)
@@ -81,11 +79,11 @@
(should
(equal
nil
- (parser-generator--valid-look-ahead-p '(f e))))
+ (parser-generator--valid-look-ahead-p '(f $))))
(should
(equal
t
- (parser-generator--valid-look-ahead-p '(e e))))
+ (parser-generator--valid-look-ahead-p '($ $))))
(message "Passed with look-ahead number is 2")
@@ -101,15 +99,15 @@
(should
(equal
- '(("a") ("b") (e))
+ '(($) ("a") ("b"))
(parser-generator--get-grammar-look-aheads)))
- (message "Passed ((a) (b) (e))")
+ (message "Passed ((a) (b) ($))")
(parser-generator-set-look-ahead-number 2)
(should
(equal
- '(("a" "a") ("a" "b") ("a" e) ("b" "a") ("b" "b") ("b" e) (e e))
+ '(($ $) ("a" $) ("a" "a") ("a" "b") ("b" $) ("b" "a") ("b" "b"))
(parser-generator--get-grammar-look-aheads)))
(message "Passed tests for (parser-generator--get-grammar-look-aheads)"))
- [elpa] externals/parser-generator d360e8a 176/434: Added failing unit test for FIRST function with starting e-identifier, (continued)
- [elpa] externals/parser-generator d360e8a 176/434: Added failing unit test for FIRST function with starting e-identifier, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator c1cdf20 197/434: Fixed issue with lex analyzer reached end of input, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 446cbe9 217/434: Refactored unit tests and separated k=2 case, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 1818b9d 199/434: Added error in action-tables generation if no accept action is found, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 54857e4 220/434: Added failing unit test for translation via LRk, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator a96ab3a 222/434: More debugging LR k > 1, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 783ea61 227/434: Added translation-symbol-table to incremental parser and translater, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 439d894 228/434: Passed all LR k=1 tests with more work on generalized solution, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 47fb35e 229/434: More work on a more generalized LR Parser, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 9b6e076 231/434: Using lowercase epsilon for e-identifier comment, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 01173e2 230/434: Added EOF identifier, passing all unit tests,
ELPA Syncer <=
- [elpa] externals/parser-generator a76bb98 240/434: Added comments, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 3807a72 237/434: Added failing unit test for LR-items k=2, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 40473d3 252/434: Fixed bug with data in full look-ahead in parse function, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator e1315c3 246/434: Updated so E-FREE-FIRST(x) only uses E-FREE-FIRST on first symbol, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 53ae129 245/434: Commented out useless code, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 24e96cb 261/434: Improved description of LRk, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 40907b7 257/434: white-space fixes, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 37d9fcb 260/434: Improved documentation, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 08b696f 267/434: Fixed typo in doc about token, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator b80fc6e 264/434: Updated README, ELPA Syncer, 2021/11/29