[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/parser-generator 8013f69 384/434: Unit tests for testin
From: |
ELPA Syncer |
Subject: |
[elpa] externals/parser-generator 8013f69 384/434: Unit tests for testing precedence table generation now passes |
Date: |
Mon, 29 Nov 2021 16:00:21 -0500 (EST) |
branch: externals/parser-generator
commit 8013f693cb1c97c81186b1734d6b979e5c735281
Author: Christian Johansson <christian@cvj.se>
Commit: Christian Johansson <christian@cvj.se>
Unit tests for testing precedence table generation now passes
---
parser-generator-lr.el | 88 ++++++++-
test/parser-generator-lr-test.el | 389 ++-------------------------------------
2 files changed, 93 insertions(+), 384 deletions(-)
diff --git a/parser-generator-lr.el b/parser-generator-lr.el
index be88680..1cd0534 100644
--- a/parser-generator-lr.el
+++ b/parser-generator-lr.el
@@ -161,12 +161,88 @@
line-index
(1+ line-index))))
- ;; TODO Go through production-numbers
- ;; TODO Look for attributes
- ;; TODO Look for precedence-attributes
- ;; TODO If none was found, iterate symbols
- ;; TODO If found a last terminal, use it's precedence type and value
- ;; TODO for the rule
+ ;; Go through production-numbers
+ (let ((productions (parser-generator--get-grammar-productions))
+ (production-number 0))
+ (dolist (production productions)
+ (let ((production-precedence-value)
+ (production-precedence-type))
+
+ ;; 1. Look for attributes
+ ;; 2. Look for precedence-attribute
+ ;; 3. Look for value and type of precedence-attribute
+ (when parser-generator-lr--context-sensitive-precedence-attribute
+ (let ((production-attributes
+
(parser-generator--get-grammar-context-sensitive-attributes-by-production-number
+ production-number)))
+ (when production-attributes
+ (let ((production-precedence-attribute
+ (plist-get
+ production-attributes
+
parser-generator-lr--context-sensitive-precedence-attribute)))
+ (when production-precedence-attribute
+ (let ((production-precedence-attribute-value
+ (parser-generator-lr--get-symbol-precedence-value
+ production-precedence-attribute))
+ (production-precedence-attribute-type
+ (parser-generator-lr--get-symbol-precedence-type
+ production-precedence-attribute)))
+ (when (and
+ production-precedence-attribute-value
+ production-precedence-attribute-type)
+ (setq
+ production-precedence-value
+ production-precedence-attribute-value
+ )
+ (setq
+ production-precedence-type
+ production-precedence-attribute-type))))))))
+
+ ;; 1. If none was found
+ ;; 2. Iterate symbols of production RHS
+ ;; 3. If found a last terminal of RHS
+ ;; 4. Look for a precedence value and type of it
+ (unless production-precedence-value
+ (let ((rhs (car (cdr production)))
+ (rhs-last-terminal))
+ (dolist (rhs-element rhs)
+ (when (parser-generator--valid-terminal-p
+ rhs-element)
+ (setq
+ rhs-last-terminal
+ rhs-element)))
+
+ (when rhs-last-terminal
+ (let ((terminal-precedence-value
+ (parser-generator-lr--get-symbol-precedence-value
+ rhs-last-terminal))
+ (terminal-precedence-type
+ (parser-generator-lr--get-symbol-precedence-type
+ rhs-last-terminal)))
+ (when (and
+ terminal-precedence-value
+ terminal-precedence-type)
+ (setq
+ production-precedence-value
+ terminal-precedence-value)
+ (setq
+ production-precedence-type
+ terminal-precedence-type))))))
+
+ (when (and
+ production-precedence-type
+ production-precedence-value)
+ (puthash
+ production-number
+ production-precedence-value
+ parser-generator-lr--production-number-precedence-value)
+ (puthash
+ production-number
+ production-precedence-type
+ parser-generator-lr--production-number-precedence-type))
+ (setq
+ production-number
+ (1+ production-number)))))
)))
diff --git a/test/parser-generator-lr-test.el b/test/parser-generator-lr-test.el
index d3a7162..50a9e22 100644
--- a/test/parser-generator-lr-test.el
+++ b/test/parser-generator-lr-test.el
@@ -57,7 +57,7 @@
"Test `parser-generator-lr--generate-precedence-tables'."
(message "Starting tests for
(parser-generator-lr--generate-precedence-tables)")
- ;; TODO Test getting token precedence value and type
+ ;; Test getting token precedence value and type
(setq
parser-generator--global-attributes
'(%left %precedence %right))
@@ -68,6 +68,9 @@
parser-generator--context-sensitive-attributes
'(%prec))
(setq
+ parser-generator-lr--context-sensitive-precedence-attribute
+ '%prec)
+ (setq
parser-generator--global-declaration
'((%left a)
(%right b)
@@ -80,7 +83,7 @@
(
(Sp S)
(S (A c) B)
- (A (a b))
+ (A (a b %prec a))
(B (a b c %prec FIRST))
)
Sp))
@@ -142,14 +145,14 @@
nil
(parser-generator-lr--get-production-number-precedence-value 2)))
- ;; A -> a b
+ ;; A -> a b %prec a
(should
(equal
- '%right
+ '%left
(parser-generator-lr--get-production-number-precedence-type 3)))
(should
(equal
- 1
+ 0
(parser-generator-lr--get-production-number-precedence-value 3)))
;; B -> a b c %prec FIRST
@@ -159,8 +162,9 @@
(parser-generator-lr--get-production-number-precedence-type 4)))
(should
(equal
- 4
+ 3
(parser-generator-lr--get-production-number-precedence-value 4)))
+ (message "Passed generation of precedence value and type of productions.")
;; Grammar with conflicts that can be resolved
;; using context-sensitive precedence attributes
@@ -905,376 +909,6 @@
(message "Passed tests for (parser-generator-lr--parse)"))
-(defun parser-generator-lr-test-infix-calculator ()
- "Test infix calculator example."
-
- ;; https://www.gnu.org/software/bison/manual/html_node/Infix-Calc.html
- ;; Lex-analyzer
- (setq
- parser-generator-lex-analyzer--function
- (lambda (index)
- (with-current-buffer "*buffer*"
- (let ((token))
- (when
- (<
- index
- (point-max))
- (goto-char
- index)
-
- ;; Skip white-space(s)
- (when (looking-at-p "[\t ]+")
- (when
- (search-forward-regexp "[^\t ]" nil t)
- (forward-char -1)))
-
- (cond
- ((looking-at "\\([0-9]+\\.[0-9]+\\|[0-9]+\\)")
- (setq
- token
- `(NUM ,(match-beginning 0) . ,(match-end 0))))
- ((looking-at "\\(\\+\\|-\\|*\\|/\\|\\^\\|)\\|(\\|\n\\)")
- (let ((symbol
- (buffer-substring-no-properties
- (match-beginning 0)
- (match-end 0))))
- (setq
- token
- `(,symbol ,(match-beginning 0) . ,(match-end 0)))))
- (t (error "Unexpected input at %d!" index))))
- 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))
- (let ((symbol
- (buffer-substring-no-properties start end)))
- (when
- (string-match-p "^\\([0-9]+\\.[0-9]+\\|[0-9]+\\)$" symbol)
- (setq
- symbol
- (string-to-number symbol)))
- symbol))))))
- (setq
- parser-generator--global-attributes
- '(%left %precedence %right))
- (setq
- parser-generator-lr--global-precedence-attributes
- '(%left %precedence %right))
- (setq
- parser-generator--global-declaration
- '(
- (%left "-" "+")
- (%left "*" "/")
- (%precedence NEG)
- (%right "^")))
- (setq
- parser-generator--context-sensitive-attributes
- '(%prec))
- (setq
- parser-generator-lr--precedence-comparison-function
- (lambda(a b)
- (if (and
- (not a)
- (not b))
- nil
- (let ((a-precedence)
- (b-precedence))
- (when a
- (setq
- a-precedence
- (plist-get
- a
- '%precedence)))
- (when b
- (setq
- b-precedence
- (plist-get
- b
- '%precedence)))
- (cond
- ((and
- a-precedence
- (not b-precedence))
- t)
- ((and
- b-precedence
- (not a-precedence))
- nil)
- ((and
- a-precedence
- b-precedence
- (>
- a-precedence
- b-precedence))
- t)
- ((and
- a-precedence
- b-precedence
- (<
- a-precedence
- b-precedence))
- nil)
- ((and
- a-precedence
- b-precedence
- (=
- a-precedence
- b-precedence))
- ;; TODO Fix this
- ;; TODO if a-precedence-value > b-precedence-value then reduce (t)
- ;; TODO if a-precedence-value < b-precedence-value then shift (nil)
- ;; TODO if a-precedence-value equal be-precedence-value then let
operator decide
- (cond
- ((equal a-precedence))
- )))))))
- (parser-generator-set-grammar
- '(
- (start input line exp)
- ("+" "-" "*" "/" "^" "(" ")" "\n" NUM)
- (
- (start input)
- (input
- %empty
- (input line (lambda(args) (nth 1 args))))
- (line
- "\n"
- (exp "\n" (lambda(args) (nth 0 args))))
- (exp
- NUM
- (exp "+" exp (lambda(args) (+ (nth 0 args) (nth 2 args))))
- (exp "-" exp (lambda(args) (- (nth 0 args) (nth 2 args))))
- (exp "*" exp (lambda(args) (* (nth 0 args) (nth 2 args))))
- (exp "/" exp (lambda(args) (/ (nth 0 args) (nth 2 args))))
- ("-" exp %prec NEG (lambda(args) (- (nth 1 args))))
- (exp "^" exp (lambda(args) (expt (nth 0 args) (nth 2 args))))
- ("(" exp ")" (lambda(args) (nth 1 args)))))
- start))
-
- (setq
- parser-generator--e-identifier
- '%empty)
- (parser-generator-set-look-ahead-number
- 1)
-
- ;; Add global symbol precedence and also
- ;; context-sensitive precedence and grammar should now pass without conflicts
- (setq
- parser-generator--context-sensitive-attributes
- '(%prec))
- (setq
- parser-generator--global-attributes
- '(%left %precedence %right))
- (setq
- parser-generator-lr--global-precedence-attributes
- '(%left %precedence %right))
- (setq
- parser-generator-lr--context-sensitive-precedence-attribute
- '%prec)
- ;; https://www.gnu.org/software/bison/manual/html_node/How-Precedence.html
- (setq
- parser-generator-lr--precedence-comparison-function
- (lambda(a b)
- (let ((a-max-op)
- (a-max-value)
- (b-max-op)
- (b-max-value))
- (when a
- (let ((a-left (plist-get a '%left))
- (a-precedence (plist-get a '%precedence))
- (a-right (plist-get a '%right)))
- (when (and
- a-left
- (or
- (not a-max-value)
- (> a-left a-max-value)))
- (setq a-max-op '%left)
- (setq a-max-value a-left))
- (when (and
- a-precedence
- (or
- (not a-max-value)
- (> a-precedence a-max-value)))
- (setq a-max-op '%precedence)
- (setq a-max-value a-precedence))
- (when (and
- a-right
- (or
- (not a-max-value)
- (> a-right a-max-value)))
- (setq a-max-op '%right)
- (setq a-max-value a-right))))
- (when b
- (let ((b-left (plist-get b '%left))
- (b-precedence (plist-get b '%precedence))
- (b-right (plist-get b '%right)))
- (when (and
- b-left
- (or
- (not b-max-value)
- (> b-left b-max-value)))
- (setq b-max-op '%left)
- (setq b-max-value b-left))
- (when (and
- b-precedence
- (or
- (not b-max-value)
- (> b-precedence b-max-value)))
- (setq b-max-op '%precedence)
- (setq b-max-value b-precedence))
- (when (and
- b-right
- (or
- (not b-max-value)
- (> b-right b-max-value)))
- (setq b-max-op '%right)
- (setq b-max-value b-right))))
- (cond
- ((and
- a-max-value
- (or
- (not b-max-value)
- (> a-max-value b-max-value)))
- t)
- ((and
- b-max-value
- (or
- (not a-max-value)
- (> b-max-value a-max-value)))
- nil)
- ((and
- a-max-value
- b-max-value
- (= a-max-value b-max-value))
- (cond
- ((or
- (equal a-max-op '%left)
- (equal a-max-op '%precedence))
- t)
- (t nil)))))))
- (setq
- parser-generator--global-declaration
- '(
- (%left "-" "+")
- (%left "*" "/")
- (%precedence NEG)
- (%right "^")
- ))
- (parser-generator-set-grammar
- '(
- (start input line exp)
- ("+" "-" "*" "/" "^" "(" ")" "\n" NUM)
- (
- (start input)
- (input
- %empty
- (input line (lambda(args) (nth 1 args))))
- (line
- "\n"
- (exp "\n" (lambda(args) (nth 0 args))))
- (exp
- NUM
- (exp "+" exp (lambda(args) (+ (nth 0 args) (nth 2 args))))
- (exp "-" exp (lambda(args) (- (nth 0 args) (nth 2 args))))
- (exp "*" exp (lambda(args) (* (nth 0 args) (nth 2 args))))
- (exp "/" exp (lambda(args) (/ (nth 0 args) (nth 2 args))))
- ("-" exp %prec NEG (lambda(args) (- (nth 1 args))))
- (exp "^" exp (lambda(args) (expt (nth 0 args) (nth 2 args))))
- ("(" exp ")" (lambda(args) (nth 1 args)))))
- start))
- (parser-generator-process-grammar)
-
- (parser-generator-lr-generate-parser-tables)
- (let ((buffer (generate-new-buffer "*buffer*")))
-
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
- (insert "4* 5 + 3\n")
- (should
- (equal
- 23
- (parser-generator-lr-translate)))
- (message "Passed 4* 5 + 3 with correct result")
-
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
- (insert "10/1+1\n")
- (should
- (equal
- 11
- (parser-generator-lr-translate)))
- (message "Passed 10/1+1 with correct result")
-
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
- (insert "10^2+3\n")
- (should
- (equal
- 103
- (parser-generator-lr-translate)))
- (message "Passed 10^2+3 with correct result")
-
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
- (insert "-33+5\n")
- (should
- (equal
- -28
- (parser-generator-lr-translate)))
- (message "Passed -33+5 with correct result")
-
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
- (insert "- 33 - 3\n")
- (should
- (equal
- -36
- (parser-generator-lr-translate)))
- (message "Passed - 33 - 3 with correct result")
-
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
- (insert "3 ^ 2\n")
- (should
- (equal
- 9
- (parser-generator-lr-translate)))
- (message "Passed 3 ^ 2 with correct result")
-
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
- (insert "-56 + 2\n")
- (should
- (equal
- -54
- (parser-generator-lr-translate)))
- (message "Passed -56 + 2 with correct result")
-
- ;; TODO This should work
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
- (insert "4 + 5 *3\n")
- (should
- (equal
- 19
- (parser-generator-lr-translate)))
- (message "Passed 4 + 5 *3 with correct result")
-
- (switch-to-buffer buffer)
- (kill-region (point-min) (point-max))
- (insert "4 + 4.5 - (34/(8*3+-3))\n")
- (should
- (equal
- 6.880952381
- (parser-generator-lr-translate)))
- (message "Passed 4 + 4.5 - (34/(8*3+-3)) with correct result")
-
- (kill-buffer))
- )
-
(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")
@@ -2047,8 +1681,7 @@
(parser-generator-lr-test-parse)
(parser-generator-lr-test-translate)
(parser-generator-lr-test-parse-k-2)
- (parser-generator-lr-test-parse-k-0)
- (parser-generator-lr-test-infix-calculator))
+ (parser-generator-lr-test-parse-k-0))
(provide 'parser-generator-lr-test)
- [elpa] externals/parser-generator feaa9ff 338/434: Removed debug outputs, (continued)
- [elpa] externals/parser-generator feaa9ff 338/434: Removed debug outputs, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator cf01b59 341/434: Fixed action-table generation with symbols with context-sensitive attributes, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator ae18945 353/434: Passing some calculations thanks to precedence / associativity, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator fce14ea 355/434: Fixed bug with context-sensitive attributes being lost in LR-item generation, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 2592481 361/434: Added TODO notes, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 18b2f7b 365/434: Added context-sensitive precedence to infix example, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 3170e8d 370/434: Context-sensitive precedence now avoids conflict-detection, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 1be5fda 374/434: More work on support for conflict resolution, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 8e462cf 378/434: Validated generated action and goto-tables after precedence modification, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 6a7343e 383/434: Started on refactoring precedence table generation, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 8013f69 384/434: Unit tests for testing precedence table generation now passes,
ELPA Syncer <=
- [elpa] externals/parser-generator e070522 396/434: Fixed broken link in documentation, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 5b95baf 401/434: More work on last feature, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 4da88bf 406/434: Added another test for e-identifier in middle of rule, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 72796d0 408/434: Fixed bug with FIRST calculation with multiple symbols and e-identifiers, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 843bc57 398/434: Fixed invalid reference to parser-generator to fetch translation by production number, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 7eb8cab 397/434: Small fixes to documentation about syntax analysis, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 3a178ed 393/434: Exported LR parser now passes all tests, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator c606043 389/434: Passing all tests with new precedence generation, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator cfa9561 407/434: Added TODO item, ELPA Syncer, 2021/11/29
- [elpa] externals/parser-generator 21fef5c 388/434: Passing all tests for infix calculator, ELPA Syncer, 2021/11/29