branch: externals/parser-generator
commit 16bb2d8863a0f637bb16965654cb5fed1e006817
Author: Christian Johansson <[email protected]>
Commit: Christian Johansson <[email protected]>
Added translation example LRk parser
---
docs/Syntax-Analysis/LRk.md | 111 ++++++++++++++++++++++++++++++++++++++------
1 file changed, 97 insertions(+), 14 deletions(-)
diff --git a/docs/Syntax-Analysis/LRk.md b/docs/Syntax-Analysis/LRk.md
index 6c6eec7..04c8d59 100644
--- a/docs/Syntax-Analysis/LRk.md
+++ b/docs/Syntax-Analysis/LRk.md
@@ -15,12 +15,12 @@ A valid LR-item for a viable prefix has this structure:
Example with grammar with production: S -> SaSb and S is non-terminal and a, b
are terminals. Look-ahead number: 1
``` emacs-lisp
-(S nil (S a S b) (a))
+((S) nil (S a S b) (a))
```
* A is the production LHS
-* B, C is parts of the production RHS, if the dot is the left B is nil and C
is the entire RHS. If the dot is at the right then B is the production RHS and
C is nil, otherwise B and C contains parts of the RHS
-* L is the terminal look-ahead
+* B, C is parts of the production RHS, if the dot is at the left B is nil and
C is the entire RHS. If the dot is at the right then B is the production RHS
and C is nil, otherwise B and C contains parts of the RHS
+* L is the item look-ahead
## LR items for prefix (S)
@@ -35,12 +35,12 @@ Calculate the set of LR items valid for any viable prefix S.
(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--lr-items-for-prefix 'e)))
+ '(((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)))
```
``` emacs-lisp
@@ -52,10 +52,10 @@ Calculate the set of LR items valid for any viable prefix S.
(should
(equal
- '((S (S) (a S b) (a))
- (S (S) (a S b) (e))
- (Sp (S) nil (e)))
- (parser--lr-items-for-prefix 'S)))
+ '(((S) (S) (a S b) ($))
+ ((S) (S) (a S b) (a))
+ ((Sp) (S) nil ($)))
+ (parser-generator-lr--items-for-prefix 'S)))
```
## Parse
@@ -93,6 +93,89 @@ Perform a right-parse of input-stream.
## Translate
-Coming soon!
+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)
+ (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))
+```
[Back to syntax analysis](../../Syntax-Analysis.md)