This is an automated email from the ASF dual-hosted git repository.

aradzinski pushed a commit to branch NLPCRAFT-247
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git


The following commit(s) were added to refs/heads/NLPCRAFT-247 by this push:
     new 2dd25ac  WIP.
2dd25ac is described below

commit 2dd25acb69e6633a7961e14dd864a3fa925e9966
Author: Aaron Radzinski <[email protected]>
AuthorDate: Mon Feb 22 17:08:39 2021 -0800

    WIP.
---
 .../nlpcraft/common/makro/NCMacroCompiler.scala    | 30 ++++++++++----------
 .../common/makro/NCMacroCompilerSpec.scala         | 32 ++++++++++++++++++++--
 2 files changed, 44 insertions(+), 18 deletions(-)

diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/makro/NCMacroCompiler.scala
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/makro/NCMacroCompiler.scala
index 16a43a6..ac07f74 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/makro/NCMacroCompiler.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/makro/NCMacroCompiler.scala
@@ -59,11 +59,7 @@ object NCMacroCompiler extends LazyLogging {
          * @param s
          * @return
          */
-        private def add(optS: String, s: String): String =
-            if (optS.isEmpty)
-                s
-            else
-                optS + " " + s
+        private def concat(optS: String, s: String): String = if 
(optS.isEmpty) s else optS + " " + s
 
         /**
           *
@@ -77,26 +73,29 @@ object NCMacroCompiler extends LazyLogging {
         override def enterExpr(ctx: NCMacroDslParser.ExprContext): Unit = {
             val buf = mutable.Buffer.empty[String]
 
+            // NOTE: do not allow expression's buffer to be empty.
+            // Add harmless empty string.
             buf += ""
 
             stack.push(StackItem(buf, false))
         }
 
-        override def enterGroup(ctx: P.GroupContext): Unit =
+        override def enterGroup(ctx: P.GroupContext): Unit = {
+            // NOTE: group cannot be empty based on the BNF grammar.
             stack.push(StackItem(mutable.Buffer.empty[String], true))
+        }
 
         override def exitExpr(ctx: NCMacroDslParser.ExprContext): Unit = {
             if (stack.size > 1) {
                 val expr = stack.pop()
+                val prn = stack.top
 
                 require(expr.buffer.nonEmpty)
 
-                val prn = stack.top
-
                 if (prn.isGroup)
                     prn.buffer ++= expr.buffer
                 else
-                    prn.buffer = for (z ← expr.buffer; i ← prn.buffer.indices) 
yield add(prn.buffer(i), z)
+                    prn.buffer = for (z ← expr.buffer; i ← prn.buffer.indices) 
yield concat(prn.buffer(i), z)
             }
         }
 
@@ -108,7 +107,7 @@ object NCMacroCompiler extends LazyLogging {
             val prn = stack.top
 
             prn.buffer = prn.buffer.flatMap {
-                s ⇒ (for (z ← grp.buffer; i ← min to max) yield add(s, s"$z " 
* i).trim).toSet
+                s ⇒ (for (z ← grp.buffer; i ← min to max) yield concat(s, s"$z 
" * i).trim).toSet
             }
 
             // Reset min max.
@@ -119,11 +118,10 @@ object NCMacroCompiler extends LazyLogging {
         override def exitSyn(ctx: P.SynContext): Unit = {
             val syn = if (ctx.TXT() != null) ctx.TXT().getText else 
ctx.INT().getText
             val buf = stack.top.buffer
-            
-            if (buf.isEmpty)
-                buf += syn
-            else
-                for (i ← buf.indices) buf.update(i, add(buf(i), syn))
+
+            require(buf.nonEmpty)
+
+            for (i ← buf.indices) buf.update(i, concat(buf(i), syn))
         }
     
         override def exitList(ctx: P.ListContext): Unit =
@@ -150,7 +148,7 @@ object NCMacroCompiler extends LazyLogging {
             }
             
             if (min < 0 || max < 0 || min > max || max == 0)
-                throw error(s"Min/max quantifiers should satisfy 'max >= min, 
min >= 0, max > 0': [$min, $max]")
+                throw error(s"[min,max] quantifiers should satisfy 'max >= 
min, min >= 0, max > 0': [$min, $max]")
         }
     
         /**
diff --git 
a/nlpcraft/src/test/scala/org/apache/nlpcraft/common/makro/NCMacroCompilerSpec.scala
 
b/nlpcraft/src/test/scala/org/apache/nlpcraft/common/makro/NCMacroCompilerSpec.scala
index 3f0880e..123a18d 100644
--- 
a/nlpcraft/src/test/scala/org/apache/nlpcraft/common/makro/NCMacroCompilerSpec.scala
+++ 
b/nlpcraft/src/test/scala/org/apache/nlpcraft/common/makro/NCMacroCompilerSpec.scala
@@ -19,6 +19,7 @@ package org.apache.nlpcraft.common.makro
 
 import org.junit.jupiter.api.Assertions.assertTrue
 import org.junit.jupiter.api.Test
+import  org.apache.nlpcraft.common._
 
 /**
   * Unit tests for the macro compiler.
@@ -38,26 +39,53 @@ class NCMacroCompilerSpec {
         
         assertTrue(res == z)
     }
+
+    /**
+     *
+     * @param txt
+     */
+    private def checkError(txt: String): Unit = {
+        try {
+            NCMacroCompiler.compile(txt)
+
+            assert(false)
+        } catch {
+            case e: NCE ⇒
+                println(e.getMessage)
+                assert(true)
+        }
+    }
     
     @Test
-    def testCompiler(): Unit = {
+    def testOkCompiler(): Unit = {
         checkEq("A", Seq("A"))
         checkEq("    A   ", Seq("A"))
         checkEq("A B", Seq("A B"))
         checkEq("A           B", Seq("A B"))
         checkEq("{A}", Seq("A"))
+        checkEq("{{{A}}[1,1]}[1,1]", Seq("A"))
         checkEq("XX {A}", Seq("XX A"))
         checkEq("{A}[0,2]", Seq("", "A", "A A"))
         checkEq("{A  }   [0  ,2]", Seq("", "A", "A A"))
         checkEq("{A          }", Seq("A"))
         checkEq("      {      A          }", Seq("A"))
         checkEq("{A}{B}", Seq("A B"))
+        checkEq("{A}[0,1]{  {    {B}}}", Seq("B", "A B"))
+        checkEq("{A}[0,1]{  {    {xx B}}}", Seq("xx B", "A xx B"))
         checkEq(" {  A   }{B}", Seq("A B"))
         checkEq(" {  A   }      {B}", Seq("A B"))
-        checkEq("A {B | C}", Seq("A B", "A C"))
+        checkEq("A {B | C | _}", Seq("A", "A B", "A C"))
         checkEq("{A}[2,2]", Seq("A A"))
         checkEq("{A}[1,2]", Seq("A", "A A"))
         checkEq("{A}[1,2] {B}[2,2]", Seq("A B B", "A A B B"))
+        checkEq("yy {xx A|_}[1,2] zz", Seq("yy zz", "yy xx A zz", "yy xx A xx 
A zz"))
+        checkEq("yy {xx A|_}[0,2] zz", Seq("yy zz", "yy xx A zz", "yy xx A xx 
A zz"))
         checkEq("A {B| xxx {C|E}} D", Seq("A B D", "A xxx C D", "A xxx E D"))
     }
+
+    @Test
+    def testFailCompiler(): Unit = {
+        checkError("{A")
+        checkError("{A}[2,1]")
+    }
 }

Reply via email to