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

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

[elpa] externals/parser-generator 53fb785 395/434: Verified examples in


From: ELPA Syncer
Subject: [elpa] externals/parser-generator 53fb785 395/434: Verified examples in documentation, added infix notation calculator example
Date: Mon, 29 Nov 2021 16:00:23 -0500 (EST)

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

    Verified examples in documentation, added infix notation calculator example
---
 docs/Syntax-Analysis/LR0.md                  | 175 ++++++++++++++++-----------
 docs/Syntax-Analysis/LRk-Infix-Calculator.md | 120 ++++++++++++++++++
 docs/Syntax-Analysis/LRk.md                  |   3 +
 test/parser-generator-lr-export-test.el      |  58 +++++++++
 4 files changed, 285 insertions(+), 71 deletions(-)

diff --git a/docs/Syntax-Analysis/LR0.md b/docs/Syntax-Analysis/LR0.md
index fed7694..e031b2f 100644
--- a/docs/Syntax-Analysis/LR0.md
+++ b/docs/Syntax-Analysis/LR0.md
@@ -26,6 +26,8 @@ Example with grammar with production: S -> SaSb and S is 
non-terminal and a, b a
 You can set global symbol operator precedence and also context-sensitive 
precedence, like in GNU Bison. Example
 
 ``` emacs-lisp
+(require 'parser-generator-lr)
+
 (setq
    parser-generator--global-attributes
    '(%left %precedence %right))
@@ -66,42 +68,53 @@ Perform a right-parse of input-stream. Example from 
[Wikipedia](https://en.wikip
 (require 'ert)
 
 (let ((buffer (generate-new-buffer "*a*")))
-  (switch-to-buffer buffer)
-  (kill-region (point-min) (point-max))
-  (insert "1+1")
-
-  (parser-generator-set-grammar
-   '((S E B) ("*" "+" "0" "1") ((S (E $)) (E (E "*" B) (E "+" B) (B)) (B ("0") 
("1"))) S))
-  (parser-generator-set-look-ahead-number 0)
-  (parser-generator-process-grammar)
-  (parser-generator-lr-generate-parser-tables)
-
-  ;; Setup lex-analyzer
-  (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
-    '(5 3 5 2)
-    (parser-generator-lr-parse)))
-  (message "Passed parse with k = 0 # 1")
+    (switch-to-buffer buffer)
+    (kill-region (point-min) (point-max))
+    (insert "1+1")
+
+    (parser-generator-set-grammar
+     '((S E B) ("*" "+" "0" "1") ((S (E $)) (E (E "*" B) (E "+" B) (B)) (B 
("0") ("1"))) S))
+    (parser-generator-set-look-ahead-number 0)
+    (parser-generator-process-grammar)
+    (parser-generator-lr-generate-parser-tables)
+
+    ;; Setup lex-analyzer
+    (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
+      '(5 3 5 2)
+      (parser-generator-lr-parse)))
+    (message "Passed parse with k = 0 # 1")
+
+    (switch-to-buffer buffer)
+    (kill-region (point-min) (point-max))
+    (insert "1+1*1")
+
+    (should
+     (equal
+      '(5 3 5 2 5 1)
+      (parser-generator-lr-parse)))
+    (message "Passed parse with k = 0 # 2")
+    (kill-buffer))
 ```
 
 ## Translate
@@ -109,42 +122,59 @@ Perform a right-parse of input-stream. Example from 
[Wikipedia](https://en.wikip
 Each production RHS can optionally contain a lambda-expression that will be 
called if specified when a reduction is made, example:
 
 ```emacs-lisp
-(let ((buffer (generate-new-buffer "*a*")))
-  (switch-to-buffer buffer)
-  (kill-region (point-min) (point-max))
-  (insert "1+1")
-
-  (parser-generator-set-grammar
-   '((S E B) ("*" "+" "0" "1") ((S (E $)) (E (E "*" B (lambda(args) (let ((ret 
(list (nth 0 args)))) (when (nth 2 args) (setq ret (append ret `(" x " ,(nth 2 
args))))) ret))) (E "+" B (lambda(args) (let ((ret (list (nth 0 args)))) (when 
(nth 2 args) (setq ret (append ret `(" . " ,(nth 2 args))))) ret))) (B)) (B 
("0") ("1"))) S))
-  (parser-generator-set-look-ahead-number 0)
-  (parser-generator-process-grammar)
-  (parser-generator-lr-generate-parser-tables)
-
-  ;; Setup lex-analyzer
-  (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))))))
+(require 'parser-generator-lr)
+(require 'ert)
 
-  (should
-   (equal
-    '((("1")) " . " ("1"))
-    (parser-generator-lr-translate)))
-  (message "Passed translation k=0")
-  (kill-buffer))
+(let ((buffer (generate-new-buffer "*a*")))
+    (switch-to-buffer buffer)
+    (kill-region (point-min) (point-max))
+    (insert "1+1")
+
+    (parser-generator-set-grammar
+     '(
+       (S E B)
+       ("*" "+" "0" "1")
+       (
+        (S (E $))
+        (E
+         (E "*" B (lambda(args) (let ((ret (list (nth 0 args)))) (when (nth 2 
args) (setq ret (append ret `(" x " ,(nth 2 args))))) ret)))
+         (E "+" B (lambda(args) (let ((ret (list (nth 0 args)))) (when (nth 2 
args) (setq ret (append ret `(" . " ,(nth 2 args))))) ret)))
+         (B)
+         )
+        (B
+         ("0")
+         ("1"))
+        )
+       S))
+    (parser-generator-set-look-ahead-number 0)
+    (parser-generator-process-grammar)
+    (parser-generator-lr-generate-parser-tables)
+
+    ;; Setup lex-analyzer
+    (setq
+     parser-generator-lex-analyzer--function
+     (lambda (index)
+       (with-current-buffer buffer
+         (when (< index (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
+      '("1" " . " "1")
+      (parser-generator-lr-translate)))
+    (message "Passed translation k=0")
+    (kill-buffer))
 ```
 
 ## Export
@@ -152,6 +182,9 @@ Each production RHS can optionally contain a 
lambda-expression that will be call
 The export should be executed after a parser has been generated, example:
 
 ```emacs-lisp
+(require 'parser-generator-lr)
+(require 'ert)
+
 (let ((buffer (generate-new-buffer "*a*")))
   (switch-to-buffer buffer)
   (kill-region (point-min) (point-max))
diff --git a/docs/Syntax-Analysis/LRk-Infix-Calculator.md 
b/docs/Syntax-Analysis/LRk-Infix-Calculator.md
new file mode 100644
index 0000000..e0ef3e0
--- /dev/null
+++ b/docs/Syntax-Analysis/LRk-Infix-Calculator.md
@@ -0,0 +1,120 @@
+# Example LR(k) Infix Calculator
+
+Example reproduced from GNU Bison manual [Infix Notation 
Calculator](https://www.gnu.org/software/bison/manual/html_node/Infix-Calc.html).
+
+``` emacs-lisp
+(require 'parser-generator-lr)
+(require 'ert)
+
+(setq
+   parser-generator--e-identifier
+   '%empty)
+(parser-generator-set-look-ahead-number 1)
+(setq
+   parser-generator--global-attributes
+   '(%left %precedence %right))
+(setq
+   parser-generator--context-sensitive-attributes
+   '(%prec))
+(setq
+   parser-generator-lr--global-precedence-attributes
+   '(%left %precedence %right))
+(setq
+   parser-generator-lr--context-sensitive-precedence-attribute
+   '%prec)
+(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) (+ (float (nth 0 args)) (nth 2 args))))
+       (exp "-" exp (lambda(args) (- (float (nth 0 args)) (nth 2 args))))
+       (exp "*" exp (lambda(args) (* (float (nth 0 args)) (nth 2 args))))
+       (exp "/" exp (lambda(args) (/ (float (nth 0 args)) (nth 2 args))))
+       ("-" exp %prec NEG (lambda(args) (- (float (nth 1 args)))))
+       (exp "^" exp (lambda(args) (expt (float (nth 0 args)) (nth 2 args))))
+       ("(" exp ")" (lambda(args) (nth 1 args)))))
+     start))
+(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))))))
+
+(parser-generator-process-grammar)
+(parser-generator-lr-generate-parser-tables)
+
+(let ((buffer (generate-new-buffer "*buffer*")))
+    (switch-to-buffer buffer)
+    (insert "4 + 4.5 - (34/(8*3+-3))\n")
+    (let ((translate (parser-generator-lr-translate)))
+      (should
+      (equal
+        6.880952380952381
+        translate)))
+    (message "Passed correct precedence of 4 + 4.5 - (34/(8*3+-3)) = 
6.880952380952381")
+      (kill-buffer))
+```
+
+[Back to LR(k) Parser](../LRk.md)
+[Back to syntax analysis](../Syntax-Analysis.md)
diff --git a/docs/Syntax-Analysis/LRk.md b/docs/Syntax-Analysis/LRk.md
index db12254..484012e 100644
--- a/docs/Syntax-Analysis/LRk.md
+++ b/docs/Syntax-Analysis/LRk.md
@@ -27,6 +27,7 @@ Example with grammar with production: S -> SaSb and S is 
non-terminal and a, b a
 You can set global symbol operator precedence and also context-sensitive 
precedence, like in GNU Bison. Example
 
 ``` emacs-lisp
+(require 'parser-generator-lr)
 (setq
    parser-generator--global-attributes
    '(%left %precedence %right))
@@ -63,6 +64,7 @@ You can set global symbol operator precedence and also 
context-sensitive precede
 Calculate the set of LR items valid for any viable prefix S.
 
 ``` emacs-lisp
+(require 'parser-generator-lr)
 (require 'ert)
 
 (parser-set-grammar '((Sp S) (a b) ((Sp S) (S (S a S b)) (S e)) Sp))
@@ -276,5 +278,6 @@ The export should be executed after a parser has been 
generated, example:
       (message "Passed parse for exported parser")))
 ```
 
+[Example LR(k) Infix Calculator](../LRk-Infix-Calculator.md)
 
 [Back to syntax analysis](../Syntax-Analysis.md)
diff --git a/test/parser-generator-lr-export-test.el 
b/test/parser-generator-lr-export-test.el
index c2f0b68..53127b0 100644
--- a/test/parser-generator-lr-export-test.el
+++ b/test/parser-generator-lr-export-test.el
@@ -250,6 +250,64 @@
           (fa-translate))))
       (message "Passed translate for exported parser")))
 
+
+  ;; Test exported LR(0) Parser
+  (generate-new-buffer "*a*")
+  (switch-to-buffer "*a*")
+  (kill-region (point-min) (point-max))
+  (insert "1+1")
+
+  (parser-generator-set-grammar
+   '((S E B) ("*" "+" "0" "1") ((S (E $)) (E (E "*" B) (E "+" B) (B)) (B ("0") 
("1"))) S))
+  (parser-generator-set-look-ahead-number 0)
+  (parser-generator-process-grammar)
+  (parser-generator-lr-generate-parser-tables)
+
+  ;; Setup lex-analyzer
+  (setq
+   parser-generator-lex-analyzer--function
+   (lambda (index)
+     (with-current-buffer "*a*"
+       (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 "*a*"
+       (let ((start (car (cdr token)))
+             (end (cdr (cdr token))))
+         (when (<= end (point-max))
+           (buffer-substring-no-properties
+            start
+            end))))))
+
+  (should
+   (equal
+    '(5 3 5 2)
+    (parser-generator-lr-parse)))
+
+  ;; Export parser
+  (let ((export (parser-generator-lr-export-to-elisp "e--")))
+
+    (with-temp-buffer
+      (insert export)
+      (eval-buffer)
+      (should
+       (equal
+        t
+        (fboundp 'e---parse)))
+
+      (when (fboundp 'e---parse)
+        (should
+         (equal
+          '(5 3 5 2)
+          (e---parse))))
+      (message "Passed parse for exported LR(0) parser")))
+  (kill-buffer)
+
   (message "Passed parse tests"))
 
 (defun parser-generator-lr-export-test-translate ()



reply via email to

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