added ~~ operator and tests for ~~ and ... operators
[sbp.git] / tests / regression.tc
index f13accf..4b1b397 100644 (file)
@@ -1,22 +1,43 @@
-testcase {
+testcase "pathological O(n^2) behavior" {
+  input "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+  output "x";
+          s = x:: ManyA!
+     ManyA =  ()
+            | x:: A ManyA
+          A = ()! ("a" & ManyAB)
+    ManyAB = ()
+            | "a" ManyAB
+            | "b" ManyAB
+
+}
+
+testcase "another O(n^2) example, tickles different epsilon behaviors" {
+  input "aaaa";
+  output "x:{x:{x:{x}}}";
+  s = x:: s A! | ()
+  A = "a" & B
+  B = () | B "a"
+}
+
+testcase "unnamed" {
     input "aaaaa";
     s = A
     A = "a" s &~ "a" A
       | "a" A &~ "a" s
 }
 
-testcase {
+testcase "unnamed" {
     input "ab c";
     output "1:{{a b} {c}}";
 
     s     = ids
-    ids   = "1":: id (" " ids &~ id ((~[])*)!)
-          | "2":: id (    ids &~ id ((~[])*)!)
+    ids   = "1":: id (" " ids &~ id ("":: ~[]*))
+          | "2":: id (    ids &~ id ("":: ~[]*))
           | id
-    id    = [a-z]++
+    id    = "":: [a-z]++
 }
 
-testcase {
+testcase "unnamed" {
     input "ab c";
 
     output "2:{{a} 1:{{b} {c}}}";
@@ -26,10 +47,10 @@ testcase {
     ids   = "1":: id " " ids
           | "2":: id     ids
           | id
-    id    = [a-z]+
+    id    = "":: [a-z]+
 }
 
-testcase {
+testcase "unnamed" {
     input "aaabbbccc";
     output "ab";
 
@@ -42,7 +63,7 @@ testcase {
     d     = "a" d "b" | ()
 }
 
-testcase {
+testcase "unnamed" {
     input "aaabbbbccc";
 
     s     = ab & dc
@@ -54,17 +75,17 @@ testcase {
     d     = "a" d "b" | ()
 }
 
-testcase {
+testcase "unnamed" {
     input "aabb";
     output "xbx:{{a} abab:{a b} {b}}";
 
     x     = ~[]
-    s     = xbx:: x* b x*
+    s     = xbx:: ("":: x*) b ("":: x*)
     b     = abab:: [ab][ab]
          &~ ("aa"|"bb")
 }
 
-testcase {
+testcase "unnamed" {
     input  "qxbambambam";
     output "bam:{a bam:{a bam:{a x}}}";
 
@@ -74,7 +95,7 @@ testcase {
     a   = a:: ()
 }
 
-testcase {
+testcase "unnamed" {
     input  "baaaa";
     output "s2:{b0 a:{a:{epsilon}}}";
     output "b:{a:{a:{epsilon}} epsilon}";
@@ -86,9 +107,9 @@ testcase {
         | epsilon:: ()
 }
 
-testcase {
+testcase "qaq" {
     input  "qaq";
-    output "q:{a:{s1:{epsilon}}}";
+    output "q:{a:{s1}}";
 
     s   = ^"q" x "q"
     x   = ^"a" a
@@ -96,7 +117,7 @@ testcase {
     a   = s1:: x
 }
 
-testcase {
+testcase "unnamed" {
     input "baa";
     output "s1:{a2:{a2:{a0 b0} b0}}";
 
@@ -106,7 +127,7 @@ testcase {
     b   = b0:: ()
 }
 
-testcase {
+testcase "epsilon forests" {
     input  "aaa";
 
     output "s3:{s3:{epsilon a0 epsilon epsilon} epsilon epsilon epsilon}";
@@ -126,7 +147,7 @@ testcase {
         | epsilon:: ()
 }
 
-testcase {
+testcase "unnamed" {
     input "aa";
     output "poo:{poo:{poox poox} poox}";
     output "poo:{poox poo:{poox poox}}";
@@ -134,7 +155,7 @@ testcase {
         | poox:: ()
 }
 
-testcase {
+testcase "unnamed" {
     input "baa";
     output "s:{aa:{aa:{a b} b}}";
     s   = s:: "b" a
@@ -143,7 +164,7 @@ testcase {
     b   = b:: ()
 }
 
-testcase {
+testcase "unnamed" {
     input "aaab";
     output "sx:{b aa:{aa:{b b} b}}";
     s   = sx:: b d "a" "b"
@@ -154,7 +175,7 @@ testcase {
     b   = b::  ()
 }
 
-testcase {
+testcase "a+(b*c)" {
     input "a+(b*c)";
     output "+:{{a} *:{{b} {c}}}";
 
@@ -163,16 +184,16 @@ testcase {
           | r ^"*" r
           | r ^"+" r
           | "(" r ")"
-    id    = [a-z]++
+    id    = "":: [a-z]++
 }
 
-testcase {
+testcase "a+b-d*c" {
     input "a+b-d*c";
-    output "plus:{stringify:{{a}} minus:{stringify:{{b}} times:{stringify:{{d}} stringify:{{c}}}}}";
-    output "times:{plus:{stringify:{{a}} minus:{stringify:{{b}} stringify:{{d}}}} stringify:{{c}}}";
-    output "plus:{stringify:{{a}} times:{minus:{stringify:{{b}} stringify:{{d}}} stringify:{{c}}}}";
-    output "times:{minus:{plus:{stringify:{{a}} stringify:{{b}}} stringify:{{d}}} stringify:{{c}}}";
-    output "minus:{plus:{stringify:{{a}} stringify:{{b}}} times:{stringify:{{d}} stringify:{{c}}}}";
+    output "times:{plus:{stringify:{a} minus:{stringify:{b} stringify:{d}}} stringify:{c}}";
+    output "plus:{stringify:{a} times:{minus:{stringify:{b} stringify:{d}} stringify:{c}}}";
+    output "minus:{plus:{stringify:{a} stringify:{b}} times:{stringify:{d} stringify:{c}}}";
+    output "plus:{stringify:{a} minus:{stringify:{b} times:{stringify:{d} stringify:{c}}}}";
+    output "times:{minus:{plus:{stringify:{a} stringify:{b}} stringify:{d}} stringify:{c}}";
     w    = " "
     l    = id
     s    = assign:: l "=" q
@@ -187,9 +208,9 @@ testcase {
     idl    = [a-d]
 }
 
-testcase {
+testcase "a+b*c" {
     input "a+b*c";
-    output "plus:{stringify:{{a}} times:{stringify:{{b}} stringify:{{c}}}}";
+    output "plus:{stringify:{a} times:{stringify:{b} stringify:{c}}}";
     w    = " "
     l    = id
     s    = assign:: l "=" r
@@ -204,16 +225,16 @@ testcase {
     idl    = [a-d]
 }
 
-testcase {
+testcase "unnamed" {
   input "aa bb";
-  output "{q:{{a a}} q:{{b b}}}";
+  output "{q:{a a} q:{b b}}";
 
-  s    = q */ ws
+  s    = "":: q */ ws
   ws   = " "*
   q    = q:: [a-z]++
 }
 
-testcase {
+testcase "indentation" {
 
     input "
 
@@ -237,18 +258,18 @@ testcase {
 
 indent    = ww
 outdent   = " "  outdent " "
-          | " "  ((~[])*)  "\n"
+          | " "  ("":: (~[])*)  "\n"
 
 w          = " " | "\n" | "\r"
-ws         = w*
-ww         = sp*
+ws         = "":: w*
+ww         = "":: sp*
 sp         = " "
-any        = (~[])*
+any        = "":: (~[])*
 
 s          = smt:: ws! statement ws! statement ws!
 
-block       =        "\n"! indent!  blockBody
-           &~        "\n"! (" " outdent! " ") (~[\ ])! ((~[])*)!
+block       =        "\n" indent!  blockBody
+           &~        "\n" (" " outdent! " ") ~[\ ]! ("":: ~[]*)!
 
 blockBody   =       statement
             > sbb:: statement ws blockBody
@@ -263,87 +284,81 @@ expr        = ident
 
 call        = expr "()"        /ws
 
-num         = [0-9]++
+num         = "":: [0-9]++
 
-ident       = [a-z]++ &~ keyword
+ident       = "":: [a-z]++ &~ keyword
 keyword     = "if" | "then" | "else" | "while"
 
 
 
 }
 
-testcase {
+
+testcase "unnamed" {
     input "abc                         ";
 
     s     = s2:: q " "*
     q     = a3:: [a-z] [a-z] [a-z]
-         &~ (~[])! "b" ((~[])*)!
+         &~ ("":: ~[])! "b" ("":: ~[]*)!
 }
 
-testcase {
+testcase "unnamed" {
     input "abc                         ";
     output "s:{a b c}";
 
     s     = s:: [a-z] [a-z] [a-z] " "*
 }
 
-testcase {
+testcase "a+2" {
 
     input "a+2";
     output "Plus:{left:{Foo} right:{{2}}}";
 
     s       = Expr
-    Expr    = [0-9]++
+    Expr    = "":: [0-9]++
             | Plus:: (left::Expra) "+" (right::Expr)
     Expra   = Foo:: ("a" | "b")
 
 }
 
-testcase {
+testcase "unnamed" {
     input "aaaaa";
-    output "top:{a q:{{a a a}} a}";
+    output "top:{a q a}";
 
     s = top:: z (q::"a"*) z
     z = a:: "a"
 }
 
-testcase {
+testcase "dangling else" {
     input  "if (x) if (y) z else q";
-    output "if:{ident:{{x}} else:{if:{ident:{{y}} then:{ident:{{z}}}} ident:{{q}}}}";
+    output "if:{ident:{x} else:{if:{ident:{y} then:{ident:{z}}} ident:{q}}}";
 
     s      = Expr
     Expr   = if::     "if" "(" Expr ")" IfBody     /ws
            | ident::  [a-z]++
     IfBody = else::   Expr            "else"  Expr /ws
-           | then::   Expr &~   ((~[])* "else" Expr! /ws)
-    ws     = [ ]**
+           | then::   Expr &~   (("":: (~[])*) "else" Expr! /ws)
+    ws     = "":: [ ]**
 }
 
 
-testcase {
+testcase "unnamed" {
     input "12111211";
     output "ac:{{2 1 2 1}}";
-    //output "a:{{2 1 2 1}}";
-    //output "c:{{c:{1 1} c:{1 1}}}";
 
     s   = ab:: ab
         | ac:: ac
         | bc:: bc
-        //| a  =>  "a"
-        //| b  =>  "b"
-        //| c  =>  "c"
     ab   = a & b
     ac   = a & c
     bc   = b & c
-    a   = ("1" x)*
-    b   = ("b":: x "2")*
-    c   = ("c":: x "2" x "1")*
+    a   = "":: ("1" x)*
+    b   = "":: ("b":: x "2")*
+    c   = "":: ("c":: x "2" x "1")*
     x   = [123]
 }
 
-// make sure follow restrictions are honored
-// when a string matches the empty string
-testcase {
+testcase "follow restrictions on empty string" {
   input "xxx";
   s = x:: "x" A "x" C "x"
   A = B
@@ -353,17 +368,17 @@ testcase {
   D = ()
 }
 
-testcase {
+testcase "unnamed" {
   input "axxxxxc";
   output "q:{a {x x x x x} c}";
-  s  = q:: A ws B? ws C
-  ws = [x]**
+  s  = q:: A ws (B|()) ws C
+  ws = "":: [x]**
   A  = a:: "a"
   B  = b:: "b"
   C  = c:: "c"
 }
 
-testcase {
+testcase "unnamed" {
   input "aaaaaaaaaaaaaaaaaaaa";
   output "";
   s = As & AAs
@@ -371,25 +386,30 @@ testcase {
   AAs = () | AAs "aa"
 }
 
-// pathological O(n^2) behavior
-testcase {
-  input "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
-  output "x";
-          s = x:: ManyA!
-     ManyA =  ()
-            | x:: A ManyA
-          A = ()! ("a" & ManyAB)
-    ManyAB = ()
-            | "a" ManyAB
-            | "b" ManyAB
+testcase "question mark" {
+  input "aa aba abba";
+  output "s:{Y Y Z}";
+  s = s:: X " " X " " X
+  X = Y > Z
+  Y = Y:: "a" B? "a"
+  Z = Z:: "a" "b"* "a"
+  B = "b"
+}
 
+testcase "operator: ... " {
+  input "aaabbbaaa abababababa";
+  output "s:{C:{a a a b b b a a a} B:{a b a b a b a b a b a}}";
+  s:: = A " " A
+  A   = B > C
+  B:: = [ab]* &~ (... "bbb" ...)
+  C:: = [ab]*
 }
 
-// another O(n^2) example, tickles different epsilon behaviors
-testcase {
-  input "aaaa";
-  output "x:{x:{x:{x}}}";
-  s = x:: s A! | ()
-  A = "a" & B
-  B = () | B "a"
+testcase "operator: ~~" {
+  input "aaabbbaaa abababababa";
+  output "s:{C:{a a a b b b a a a} B:{a b a b a b a b a b a}}";
+  s:: = A " " A
+  A   = B > C
+  B:: = ~~(... "bbb" ...)
+  C:: = [ab]*
 }