[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/parser-generator 87ded78c28 63/82: LL(1) parser passes
From: |
Christian Johansson |
Subject: |
[elpa] externals/parser-generator 87ded78c28 63/82: LL(1) parser passes test for generating tables and parsing |
Date: |
Thu, 12 May 2022 13:28:18 -0400 (EDT) |
branch: externals/parser-generator
commit 87ded78c28b22b6fed9198bf4065203f2b495129
Author: Christian Johansson <christian@cvj.se>
Commit: Christian Johansson <christian@cvj.se>
LL(1) parser passes test for generating tables and parsing
---
parser-generator-ll.el | 167 +++++++++++++++++++++++----------------
test/parser-generator-ll-test.el | 110 +++++++++++++-------------
2 files changed, 153 insertions(+), 124 deletions(-)
diff --git a/parser-generator-ll.el b/parser-generator-ll.el
index c65e0b0b4a..fd40b6e8d4 100644
--- a/parser-generator-ll.el
+++ b/parser-generator-ll.el
@@ -40,16 +40,17 @@
(setq
list-parsing-table
(parser-generator-ll--generate-action-table-k-gt-1
- (parser-generator-ll--generate-goto-table-k-gt-1))))
+ (parser-generator-ll--generate-goto-table))))
(message "\n;; Starting generation of LL(1) tables..\n")
- (unless (parser-generator-ll--valid-grammar-p-k-eq-1)
+ (unless (parser-generator-ll--valid-grammar-k-eq-1-p)
(error "Invalid LL(1) grammar specified!"))
(setq
list-parsing-table
- (parser-generator-ll--generate-table-k-eq-1)))
+ (parser-generator-ll--generate-action-table-k-eq-1
+ (parser-generator-ll--generate-goto-table))))
;; Convert list-structure to hash-map
(dolist (state-list list-parsing-table)
@@ -92,14 +93,18 @@
"Parse input via lex-analyzer and return parse trail."
(let ((accept)
(stack
- (list
- (list
+ (if (> parser-generator--look-ahead-number 1)
+ (list
+ (list
+ (list
+ (parser-generator--get-grammar-start))
+ (parser-generator--generate-list-of-symbol
+ parser-generator--look-ahead-number
+ parser-generator--eof-identifier))
+ parser-generator--eof-identifier)
(list
- (parser-generator--get-grammar-start))
- (parser-generator--generate-list-of-symbol
- parser-generator--look-ahead-number
- parser-generator--eof-identifier))
- parser-generator--eof-identifier))
+ (parser-generator--get-grammar-start)
+ parser-generator--eof-identifier)))
(output)
(eof-look-ahead
(parser-generator--generate-list-of-symbol
@@ -196,8 +201,8 @@
;;; Algorithms
-(defun parser-generator-ll--generate-table-k-eq-1 ()
- "Generate table for LL(1) grammar."
+(defun parser-generator-ll--generate-action-table-k-eq-1 (goto-table)
+ "Generate action-table for LL(1) grammar using GOTO-TABLE."
(let ((parsing-table))
;; Iterate all possible look-aheads
@@ -248,30 +253,67 @@
parsing-table)))
;; Add non-terminal -> FIRST(non-terminal) -> reduce RHS, production-number
- (let ((non-terminals (parser-generator--get-grammar-non-terminals)))
- (dolist (non-terminal non-terminals)
- (let ((non-terminal-buffer))
- (let ((rhss (parser-generator--get-grammar-rhs non-terminal)))
- (dolist (rhs rhss)
- (let ((firsts-rhs (parser-generator--first rhs))
- (production-number
- (parser-generator--get-grammar-production-number
- (list (list non-terminal) rhs))))
- (dolist (first-rhs firsts-rhs)
+ (let ((non-terminal-look-ahead-p (make-hash-table :test 'equal))
+ (non-terminal-look-ahead-list (make-hash-table :test 'equal)))
+ (dolist (goto-row goto-table)
+ (let* ((stack (nth 0 goto-row))
+ (non-terminal (car (nth 0 stack)))
+ (local-follows (nth 1 stack))
+ (look-aheads (nth 1 goto-row)))
+ (parser-generator--debug
+ (message "\nnon-terminal: %S" non-terminal)
+ (message "local-follows: %S" local-follows)
+ (message "look-aheads: %S" look-aheads))
+ (dolist (look-ahead look-aheads)
+ (let* ((rhs
+ (nth 1 look-ahead))
+ (production
+ (list (list non-terminal) rhs))
+ (production-number
+ (parser-generator--get-grammar-production-number
+ production))
+ (look-ahead-terminal
+ (nth 0 look-ahead))
+ (hashmap-key
+ (format "%S-%S" non-terminal look-ahead-terminal)))
+ (parser-generator--debug
+ (message "\nrhs: %S" rhs)
+ (message "production: %S" production)
+ (message "production-number: %S" production-number)
+ (message "hashmap-key: %S" hashmap-key))
+ (unless (gethash hashmap-key non-terminal-look-ahead-p)
+ (let ((old-non-terminal-look-aheads
+ (gethash
+ non-terminal
+ non-terminal-look-ahead-list)))
(push
- (list first-rhs 'reduce rhs production-number)
- non-terminal-buffer)))))
- (when non-terminal-buffer
- (push
- (list
- non-terminal
- non-terminal-buffer)
- parsing-table)))))
+ (list
+ look-ahead-terminal
+ 'reduce
+ rhs
+ production-number)
+ old-non-terminal-look-aheads)
+ (puthash
+ non-terminal
+ old-non-terminal-look-aheads
+ non-terminal-look-ahead-list)
+ (puthash
+ hashmap-key
+ t
+ non-terminal-look-ahead-p)))))))
+ (maphash
+ (lambda (non-terminal look-ahead)
+ (push
+ (list
+ non-terminal
+ look-ahead)
+ parsing-table))
+ non-terminal-look-ahead-list))
parsing-table))
;; Algorithm 5.2 p. 350
-(defun parser-generator-ll--generate-goto-table-k-gt-1 ()
+(defun parser-generator-ll--generate-goto-table ()
"Construction of LL(k) GOTO-table. Output the set of LL(k) tables needed to
construct a action table for the grammar G."
(let ((tables (make-hash-table :test 'equal))
(distinct-item-p (make-hash-table :test 'equal))
@@ -347,7 +389,6 @@
first-concatenated-follow-set
nil
t))
- (local-follow)
(sub-symbol-rhss
(parser-generator--get-grammar-rhs
sub-symbol)))
@@ -374,49 +415,34 @@
(unless local-follow-set
(setq local-follow-set '(nil)))
- (when (> (length local-follow-set) 1)
- (signal
- 'error
- (list
- (format
- "There are more than one possible follow set in state!
%S -> %S + %S"
- sub-symbol
- production-rhs
- local-follow-set)
- sub-symbol
- production-rhs
- local-follow-set)))
- (setq
- local-follow
- (car local-follow-set))
-
(push
- local-follow
+ local-follow-set
sets)
(parser-generator--debug
(message
"pushed local follow set to sets: %S"
local-follow-set))
- (dolist (sub-symbol-rhs sub-symbol-rhss)
- (let* ((new-stack-item
- (list
- (list sub-symbol)
- sub-symbol-rhs
- local-follow)))
- (unless (gethash
- new-stack-item
- distinct-stack-item-p)
- (parser-generator--debug
- (message
- "new-stack-item: %S"
- new-stack-item))
- (puthash
- new-stack-item
- t
- distinct-stack-item-p)
- (push
- new-stack-item
- stack)))))))
+ (dolist (local-follow local-follow-set)
+ (dolist (sub-symbol-rhs sub-symbol-rhss)
+ (let* ((new-stack-item
+ (list
+ (list sub-symbol)
+ sub-symbol-rhs
+ local-follow)))
+ (unless (gethash
+ new-stack-item
+ distinct-stack-item-p)
+ (parser-generator--debug
+ (message
+ "new-stack-item: %S"
+ new-stack-item))
+ (puthash
+ new-stack-item
+ t
+ distinct-stack-item-p)
+ (push
+ new-stack-item
+ stack))))))))
(setq
sub-symbol-index
(1+ sub-symbol-index))))
@@ -554,7 +580,8 @@
(let ((sub-symbol (nth sub-symbol-index right-hand-side)))
(if (parser-generator--valid-non-terminal-p
sub-symbol)
- (let ((local-follow (nth non-terminal-index
local-follow-sets)))
+ (let ((local-follow
+ (car (nth non-terminal-index local-follow-sets))))
(push
(list
(list sub-symbol)
diff --git a/test/parser-generator-ll-test.el b/test/parser-generator-ll-test.el
index b0f3318796..299124950e 100644
--- a/test/parser-generator-ll-test.el
+++ b/test/parser-generator-ll-test.el
@@ -12,9 +12,9 @@
(require 'parser-generator-ll)
(require 'ert)
-(defun parser-generator-ll-test--generate-goto-table-k-gt-1 ()
- "Test `parser-generator-ll--generate-goto-table-k-gt-1'."
- (message "Started tests for
(parser-generator-ll--generate-goto-table-k-gt-1)")
+(defun parser-generator-ll-test--generate-goto-table ()
+ "Test `parser-generator-ll--generate-goto-table'."
+ (message "Started tests for (parser-generator-ll--generate-goto-table)")
(parser-generator-set-e-identifier 'e)
(parser-generator-set-look-ahead-number 2)
@@ -30,7 +30,7 @@
)
)
(parser-generator-process-grammar)
- (let ((tables (parser-generator-ll--generate-goto-table-k-gt-1)))
+ (let ((tables (parser-generator-ll--generate-goto-table)))
;; (message "tables: %S" tables)
(should
(equal
@@ -53,9 +53,9 @@
(
((S) ($ $)) ;; T0
(
- ((a b) (a A a a) ((a a)))
- ((a a) (a A a a) ((a a)))
- ((b b) (b A b a) ((b a)))
+ ((a b) (a A a a) (((a a))))
+ ((a a) (a A a a) (((a a))))
+ ((b b) (b A b a) (((b a))))
)
)
)
@@ -79,7 +79,7 @@
)
(parser-generator-process-grammar)
(let* ((tables
- (parser-generator-ll--generate-goto-table-k-gt-1)))
+ (parser-generator-ll--generate-goto-table)))
;; (message "tables: %S" tables)
(should
(equal
@@ -88,23 +88,23 @@
(
((A) (a a)) ;; T3
(
- ((a b) (S a a) ((a a)))
- ((a a) (S a a) ((a a)))
+ ((a b) (S a a) (((a a))))
+ ((a a) (S a a) (((a a))))
((b a) (b) nil)
)
)
(
((S) (a a)) ;; T2
(
- ((a b) (a b A) ((a a)))
+ ((a b) (a b A) (((a a))))
((a a) (e) nil)
)
)
(
((A) ($ $)) ;; T1
(
- ((a b) (S a a) ((a a)))
- ((a a) (S a a) ((a a)))
+ ((a b) (S a a) (((a a))))
+ ((a a) (S a a) (((a a))))
((b $) (b) nil)
)
)
@@ -112,7 +112,7 @@
((S) ($ $)) ;; T0
(
(($ $) (e) nil)
- ((a b) (a b A) (($ $)))
+ ((a b) (a b A) ((($ $))))
)
)
)
@@ -120,7 +120,7 @@
)
(message "Passed Example 5.17 p. 354")
- (message "Passed tests for
(parser-generator-ll--generate-goto-table-k-gt-1)"))
+ (message "Passed tests for (parser-generator-ll--generate-goto-table)"))
(defun parser-generator-ll-test--generate-action-table-k-gt-1 ()
"Test `parser-generator-ll--generate-action-table-k-gt-1'."
@@ -141,7 +141,7 @@
)
(parser-generator-process-grammar)
(let* ((goto-table
- (parser-generator-ll--generate-goto-table-k-gt-1))
+ (parser-generator-ll--generate-goto-table))
(action-table
(parser-generator-ll--generate-action-table-k-gt-1
goto-table)))
@@ -195,7 +195,7 @@
)
(parser-generator-process-grammar)
(let* ((goto-table
- (parser-generator-ll--generate-goto-table-k-gt-1))
+ (parser-generator-ll--generate-goto-table))
(action-table
(parser-generator-ll--generate-action-table-k-gt-1
goto-table)))
@@ -243,7 +243,7 @@
(message "Passed tests for
(parser-generator-ll--generate-action-table-k-gt-1)"))
-(defun parser-generator-ll-test--parse ()
+(defun parser-generator-ll-test-parse ()
"Test `parser-generator-ll-parse'."
(message "Started tests for (parser-generator-ll-parse)")
@@ -262,7 +262,7 @@
)
)
(parser-generator-process-grammar)
- (parser-generator-ll-generate-parser-tables)
+ (parser-generator-ll-generate-table)
(setq
parser-generator-lex-analyzer--function
(lambda (index)
@@ -304,7 +304,7 @@
)
)
(parser-generator-process-grammar)
- (parser-generator-ll-generate-parser-tables)
+ (parser-generator-ll-generate-table)
(setq
parser-generator-lex-analyzer--function
(lambda (index)
@@ -344,7 +344,7 @@
)
)
(parser-generator-process-grammar)
- (parser-generator-ll-generate-parser-tables)
+ (parser-generator-ll-generate-table)
(setq
parser-generator-lex-analyzer--function
(lambda (index)
@@ -387,7 +387,7 @@
)
)
(parser-generator-process-grammar)
- (parser-generator-ll-generate-parser-tables)
+ (parser-generator-ll-generate-table)
(setq
parser-generator-lex-analyzer--function
(lambda (index)
@@ -407,10 +407,9 @@
(car token)))
(should
(equal
- '(0 3 6 0 3 7 5 2 5) ;; Example is 1-indexed '(1 4 7 1 4 8 5 8 6 3 6 3)
+ '(0 3 6 0 3 7 4 7 5 2 5 2) ;; Example is 1-indexed '(1 4 7 1 4 8 5 8 6 3 6
3)
(parser-generator-ll-parse)))
(message "Passed example 5.12 p. 346-347")
- ;; TODO Make this pass
(message "Passed tests for (parser-generator-ll-parse)"))
@@ -524,9 +523,9 @@
(message "Passed tests for (parser-generator-ll--valid-grammar-k-gt-1-p)"))
-(defun parser-generator-ll-test--generate-table-k-eq-1 ()
- "Test `parser-generator-ll--generate-table-k-eq-1'."
- (message "Started tests for (parser-generator-ll--generate-table-k-eq-1)")
+(defun parser-generator-ll-test--generate-action-table-k-eq-1 ()
+ "Test `parser-generator-ll--generate-action-table-k-eq-1'."
+ (message "Started tests for
(parser-generator-ll--generate-action-table-k-eq-1)")
(parser-generator-set-eof-identifier '$)
(parser-generator-set-e-identifier 'e)
@@ -544,23 +543,24 @@
)
(parser-generator-process-grammar)
(let* ((tables
- (parser-generator-ll--generate-table-k-eq-1)))
+ (parser-generator-ll--generate-action-table-k-eq-1
+ (parser-generator-ll--generate-goto-table))))
;; (message "tables: %S" tables)
(should
(equal
'(
- (A
- (
- ((b) reduce (b S A) 3)
- ((a) reduce (a) 2)
- )
- )
(S
(
((b) reduce (b) 1)
((a) reduce (a A S) 0)
)
)
+ (A
+ (
+ ((b) reduce (b S A) 3)
+ ((a) reduce (a) 2)
+ )
+ )
(b (((b) pop)))
(a (((a) pop)))
($ ((($) accept)))
@@ -569,7 +569,6 @@
)))
(message "Passed Example 5.5 p. 340")
- ;; TODO Make this pass
(parser-generator-set-eof-identifier '$)
(parser-generator-set-e-identifier 'e)
(parser-generator-set-look-ahead-number 1)
@@ -588,22 +587,24 @@
)
)
(parser-generator-process-grammar)
- (let ((tables (parser-generator-ll--generate-table-k-eq-1)))
- (message "tables: %S" tables)
+ (let ((tables
+ (parser-generator-ll--generate-action-table-k-eq-1
+ (parser-generator-ll--generate-goto-table))))
+ ;; (message "tables: %S" tables)
(should
(equal
'(
- (F
+ (E
(
- (("a") reduce ("a") 7)
- (("(") reduce ("(" E ")") 6)
+ (("a") reduce (T E2) 0)
+ (("(") reduce (T E2) 0)
)
)
- (T2
+ (E2
(
- ((e) reduce (e) 5)
- ((")") reduce (e) 5)
- (("*") reduce ("*" F T2) 4)
+ (($) reduce (e) 2)
+ (("+") reduce ("+" T E2) 1)
+ ((")") reduce (e) 2)
)
)
(T
@@ -612,17 +613,18 @@
(("(") reduce (F T2) 3)
)
)
- (E2
+ (T2
(
- ((e) reduce (e) 2)
- ((")") reduce (e) 2)
- (("+") reduce ("+" T E2) 1)
+ (("+") reduce (e) 5)
+ ((")") reduce (e) 5)
+ (("*") reduce ("*" F T2) 4)
+ (($) reduce (e) 5)
)
)
- (E
+ (F
(
- (("a") reduce (T E2) 0)
- (("(") reduce (T E2) 0)
+ (("a") reduce ("a") 7)
+ (("(") reduce ("(" E ")") 6)
)
)
("a" ((("a") pop)))
@@ -635,7 +637,7 @@
tables)))
(message "Passed Example 5.12 p. 346-347")
- (message "Passed tests for (parser-generator-ll--generate-table-k-eq-1)"))
+ (message "Passed tests for
(parser-generator-ll--generate-action-table-k-eq-1)"))
(defun parser-generator-ll-test--valid-grammar-k-eq-1-p ()
"Test `parser-generator-ll--valid-grammar-k-eq-1-p'."
@@ -650,14 +652,14 @@
"Run test."
;; Helpers
+ (parser-generator-ll-test--generate-goto-table)
;; k > 1
- (parser-generator-ll-test--generate-goto-table-k-gt-1)
(parser-generator-ll-test--generate-action-table-k-gt-1)
(parser-generator-ll-test--valid-grammar-k-gt-1-p)
;; k = 1
- (parser-generator-ll-test--generate-table-k-eq-1)
+ (parser-generator-ll-test--generate-action-table-k-eq-1)
(parser-generator-ll-test--valid-grammar-k-eq-1-p)
;; Main stuff
- [elpa] externals/parser-generator ff261d9a4e 75/82: Using stack for symbols value in SDT, (continued)
- [elpa] externals/parser-generator ff261d9a4e 75/82: Using stack for symbols value in SDT, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator de7c45c511 78/82: Started with LL-export functions, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 5be162966b 80/82: Fixed byte-compilation issue in exported LL parser, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 2869417d78 31/82: Made new helper functions to make LL-parsing easier, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 23805731c1 34/82: More work on LL-parser, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 8cc2a5b315 44/82: More work on LLk parsing, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 5aeee49bd0 48/82: Added another todo note, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 4c93e895b3 49/82: Added TODO item, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator ec0711fa84 53/82: Tweaks on internal functions of LLk parsing, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator ed9933eeba 57/82: Passing a lot of LLk tests, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 87ded78c28 63/82: LL(1) parser passes test for generating tables and parsing,
Christian Johansson <=
- [elpa] externals/parser-generator 1ccc742678 72/82: LLk parser passes translation tests, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 1f36aeafdd 74/82: Updated documentation with translate example for LL(1) grammar, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 5e6ee66f1f 77/82: Added failing parse tests, Christian Johansson, 2022/05/12
- [elpa] externals/parser-generator 0a86c69ef1 19/82: More work on LL-table generation, Christian Johansson, 2022/05/12