branch: externals/parser-generator
commit 26bf153ffcab96f5f8f52ddc456479cce4baa44d
Author: Christian Johansson <christ...@cvj.se>
Commit: Christian Johansson <christ...@cvj.se>

    Setting look-ahead-number is now separated from setting grammar
---
 README.md           | 42 ++++++++++++++++++++++++++++++------------
 parser.el           | 13 ++++++++-----
 test/parser-test.el | 45 ++++++++++++++++++++++++++++++---------------
 3 files changed, 68 insertions(+), 32 deletions(-)

diff --git a/README.md b/README.md
index 892c2f9..02ce116 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ We use push down transducer (PDT) based algorithms:
 
 ## Grammar
 
-Grammar consists of `N`, `T`, `P` and `S`, where `N` is non-terminals, `T` is 
terminals, `P` is productions and `S` is start-production. N, T, P consists of 
lists of one or more strings and symbols, S is the left-hand-side (LHS) of a 
production in P. When initializing grammar you also set the number of 
look-ahead to use, like this:
+Grammar consists of `N`, `T`, `P` and `S`, where `N` is non-terminals, `T` is 
terminals, `P` is productions and `S` is start-production. Example:
 
 * N = `'(S A B C)`
 * T = `'(a b c)`
@@ -44,7 +44,7 @@ Grammar consists of `N`, `T`, `P` and `S`, where `N` is 
non-terminals, `T` is te
 * S = `'S`
 
 ``` emacs-lisp
-(parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) (C 
c e)) S) 2)
+(parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) (C 
c e)) S))
 ```
 
 ### Non-terminals
@@ -55,6 +55,10 @@ A non-terminal is either a symbol or a string so `"A"` and 
`A` are equally valid
 
 A terminal is either a symbol or a string so `"{"` and `A` are equally valid.
 
+### Sentential-form
+
+A list of one or more non-terminals and terminals, example `'(A "A" c ":")`
+
 ### Productions
 
 A production consists of a list of at least two elements. The first element is 
the left-hand-side (LHS) and should contain at least one element. The 
right-hand-side (RHS) consists of the rest of the elements, if there is more 
than one list in RHS then each list will be treated as a alternative production 
RHS.
@@ -71,42 +75,56 @@ Another example, production `S -> IF "{" EXPRESSION "}" | 
EXIT` is declared as:
 '(S (IF "{" EXPRESSION "}") EXIT)
 ```
 
-### Look-ahead number
+### Start
 
-Is a simple integer above zero.
+The start symbol is the entry-point of the grammar and should be either a 
string or a symbol and should exists in the list of productions as the LHS.
 
-### Start
+## Look-ahead number
+
+Is a simple integer above zero. You set it like this: 
`(parser--set-look-ahead-number 1)` for `1` number look-ahead.
 
-The start symbol is either a string or a symbol and should exists in the list 
of productions as the LHS.
+## Syntax-directed-translation (SDT)
+
+*WIP* Where should this be defined?
+
+## Semantic-actions (SA)
+
+*WIP* Where should this be defined?
 
 ## Functions
 
-### Calculate FIRST(k, S)
+### FIRST(S)
 
-Calculate first `k` terminals of sentential-form `S`, example:
+Calculate the first look-ahead number of terminals of the sentential-form `S`, 
example:
 
 ``` emacs-lisp
 (require 'ert)
-(parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) (C 
c e)) S) 2)
+(parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) (C 
c e)) S))
+(parser--set-look-ahead-number 2)
 (should
   (equal
     '((a) (a c) (a b) (c a) (b a) (e) (c) (b) (c b))
     (parser--first 'S)))
 ```
 
-### Calculate E-FREE-FIRST(k, S)
+### E-FREE-FIRST(S)
 
-Calculate e-free-first `k` terminals of sentential-form `S`, example:
+Calculate the e-free-first look-ahead number of terminals of sentential-form 
`S`, example:
 
 ``` emacs-lisp
 (require 'ert)
-(parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) (C 
c e)) S) 2)
+(parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) (C 
c e)) S))
+(parser--set-look-ahead-number 2)
 (should
   (equal
     '((c b) (c a))
     (parser--e-free-first 'S)))
 ```
 
+### FOLLOW(S)
+
+*WIP*
+
 ## Test
 
 Run in terminal `make clean && make tests && make compile`
diff --git a/parser.el b/parser.el
index 1208d27..43b6fa9 100644
--- a/parser.el
+++ b/parser.el
@@ -100,14 +100,17 @@
     (dolist (non-terminal non-terminals)
       (puthash non-terminal t parser--table-non-terminal-p))))
 
-(defun parser--set-grammar (G k)
-  "Set grammar G with look-ahead number K."
-  (unless (parser--valid-grammar-p G)
-    (error "Invalid grammar G!"))
+(defun parser--set-look-ahead-number (k)
+  "Set look-ahead number K."
   (unless (parser--valid-look-ahead-number-p k)
     (error "Invalid look-ahead number k!"))
+  (setq parser--look-ahead-number k))
+
+(defun parser--set-grammar (G)
+  "Set grammar G.."
+  (unless (parser--valid-grammar-p G)
+    (error "Invalid grammar G!"))
   (setq parser--grammar G)
-  (setq parser--look-ahead-number k)
   (setq parser--f-sets nil)
   (parser--load-symbols))
 
diff --git a/test/parser-test.el b/test/parser-test.el
index b66379a..11f4915 100644
--- a/test/parser-test.el
+++ b/test/parser-test.el
@@ -28,84 +28,96 @@
   "Test `parser--first'."
   (message "Starting tests for (parser--first)")
 
-  (parser--set-grammar '((S) (a) ((S a)) S) 1)
+  (parser--set-grammar '((S) (a) ((S a)) S))
+  (parser--set-look-ahead-number 1)
   (should
    (equal
     '((a))
     (parser--first 'S)))
   (message "Passed first 1 with rudimentary grammar")
 
-  (parser--set-grammar '((S) (a) ((S a)) S) 1)
+  (parser--set-grammar '((S) (a) ((S a)) S))
+  (parser--set-look-ahead-number 1)
   (should
    (equal
     '((a))
     (parser--first '(S a))))
   (message "Passed first 1b with rudimentary grammar")
 
-  (parser--set-grammar '((S) (a) ((S a)) S) 2)
+  (parser--set-grammar '((S) (a) ((S a)) S))
+  (parser--set-look-ahead-number 2)
   (should
    (equal
     '((a a))
     (parser--first '(S a))))
   (message "Passed first 1c with rudimentary grammar")
 
-  (parser--set-grammar '((S) ("a" "b" "c") ((S ("a" "b" "c"))) S) 2)
+  (parser--set-grammar '((S) ("a" "b" "c") ((S ("a" "b" "c"))) S))
+  (parser--set-look-ahead-number 2)
   (should
    (equal
     '(("a" "b"))
     (parser--first 'S)))
   (message "Passed first 2 with rudimentary grammar")
 
-  (parser--set-grammar '((S) ("a" b "c") ((S ("a" b "c"))) S) 3)
+  (parser--set-grammar '((S) ("a" b "c") ((S ("a" b "c"))) S))
+  (parser--set-look-ahead-number 3)
   (should
    (equal
     '(("a" b "c"))
     (parser--first 'S)))
   (message "Passed first 3 with rudimentary grammar")
 
-  (parser--set-grammar '((S A) (b) ((S A) (A b)) S) 2)
+  (parser--set-grammar '((S A) (b) ((S A) (A b)) S))
+  (parser--set-look-ahead-number 2)
   (should
    (equal
     '((b))
     (parser--first 'S)))
   (message "Passed first 1 with intermediate grammar")
 
-  (parser--set-grammar '((S A) ("a" "b") ((S A) (A ("b" "a"))) S) 2)
+  (parser--set-grammar '((S A) ("a" "b") ((S A) (A ("b" "a"))) S))
+  (parser--set-look-ahead-number 2)
   (should
    (equal
     '(("b" "a"))
     (parser--first 'S)))
   (message "Passed first 2 with intermediate grammar")
 
-  (parser--set-grammar '((S A) ("a" "b" "c" "d") ((S A) (A ("b" "a" "c" "d"))) 
S) 3)
+  (parser--set-grammar '((S A) ("a" "b" "c" "d") ((S A) (A ("b" "a" "c" "d"))) 
S))
+  (parser--set-look-ahead-number 3)
   (should
    (equal
     '(("b" "a" "c"))
     (parser--first 'S)))
   (message "Passed first 3 with intermediate grammar")
 
-  (parser--set-grammar '((S A B) ("c" "d") ((S A) (A B) (B "c" "d")) S) 1)
+  (parser--set-grammar '((S A B) ("c" "d") ((S A) (A B) (B "c" "d")) S))
+  (parser--set-look-ahead-number 1)
   (should
    (equal
     '(("c") ("d"))
     (parser--first 'S)))
   (message "Passed first 1 with semi-complex grammar")
 
-  (parser--set-grammar '((S A B) (a c d f) ((S (A a)) (A B) (B (c f) d)) S) 2)
+  (parser--set-grammar '((S A B) (a c d f) ((S (A a)) (A B) (B (c f) d)) S))
+  (parser--set-look-ahead-number 2)
   (should
    (equal
     '((c f) (d a))
     (parser--first 'S)))
   (message "Passed first 2 with semi-complex grammar")
 
-  (parser--set-grammar '((S A B) ("a" "c" "d" "m") ((S A) (A (B "a" "m")) (B 
"c" "d")) S) 3)
+  (parser--set-grammar '((S A B) ("a" "c" "d" "m") ((S A) (A (B "a" "m")) (B 
"c" "d")) S))
+  (parser--set-look-ahead-number 3)
   (should
    (equal
     '(("c" "a" "m") ("d" "a" "m"))
     (parser--first 'S)))
   (message "Passed first 3 with semi-complex grammar")
 
-  (parser--set-grammar '((S A B C) (a b c) ((S A B) (A (B a) e) (B (C b) C) (C 
c e)) S) 1)
+  (parser--set-grammar '((S A B C) (a b c) ((S A B) (A (B a) e) (B (C b) C) (C 
c e)) S))
+  (parser--set-look-ahead-number 1)
   (should
    (equal
     '((a) (e) (c) (b) )
@@ -113,14 +125,16 @@
   (message "Passed first 1 with complex grammar")
 
   ;; Example 5.28 p 382
-  (parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) 
(C c e)) S) 2)
+  (parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) 
(C c e)) S))
+  (parser--set-look-ahead-number 2)
   (should
    (equal
     '((a) (a c) (a b) (c a) (b a) (e) (c) (b) (c b))
     (parser--first 'S)))
   (message "Passed first 2 with complex grammar")
 
-  (parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) 
(C c e)) S) 3)
+  (parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) 
(C c e)) S))
+  (parser--set-look-ahead-number 3)
   (should
    (equal
     '((a c b) (a) (a c) (a b) (c a) (c a c) (c a b) (b a) (b a c) (b a b) (c 
b) (e) (c) (b) (c b a))
@@ -135,7 +149,8 @@
   (message "Starting tests for (parser--e-free-first)")
 
   ;; Example 5.28 p 402
-  (parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) 
(C c e)) S) 2)
+  (parser--set-grammar '((S A B C) (a b c) ((S (A B)) (A (B a) e) (B (C b) C) 
(C c e)) S))
+  (parser--set-look-ahead-number 2)
   (should
    (equal
     '((c b) (c a))

Reply via email to