You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nlpcraft.apache.org by ar...@apache.org on 2021/03/02 02:31:27 UTC

[incubator-nlpcraft] 02/02: Update NCIntentDslCompiler.scala

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

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

commit 0f302859de2244d915e63e7e782cda9c4335ae4a
Author: Aaron Radzinski <ar...@apache.org>
AuthorDate: Mon Mar 1 18:31:12 2021 -0800

    Update NCIntentDslCompiler.scala
---
 .../intent/impl/ver2/NCIntentDslCompiler.scala     | 119 ++++++++++++++-------
 1 file changed, 80 insertions(+), 39 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/ver2/NCIntentDslCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/ver2/NCIntentDslCompiler.scala
index b9b0321..a941b5a 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/ver2/NCIntentDslCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/ver2/NCIntentDslCompiler.scala
@@ -21,9 +21,10 @@ import com.typesafe.scalalogging.LazyLogging
 import org.antlr.v4.runtime._
 import org.antlr.v4.runtime.tree.ParseTreeWalker
 import org.apache.nlpcraft.common._
-import org.apache.nlpcraft.model.intent.impl.antlr4.{NCIntentDslParser ⇒ Parser, _}
+import org.apache.nlpcraft.model.intent.impl.antlr4.{NCIntentDslParser ⇒ IDP, _}
 import org.apache.nlpcraft.model.intent.utils.ver2._
-import org.apache.nlpcraft.model.{NCMetadata, NCRequest, NCToken, NCTokenPredicateContext, NCTokenPredicateResult}
+import org.apache.nlpcraft.model._
+import org.apache.nlpcraft.model.intent.impl.ver2.{NCIntentDslFragmentCache ⇒ FragCache}
 
 import java.util.Optional
 import java.util.regex.{Pattern, PatternSyntaxException}
@@ -33,7 +34,7 @@ import scala.collection.JavaConverters._
 
 object NCIntentDslCompiler extends LazyLogging {
     // Compiler cache.
-    private val cache = new mutable.HashMap[String, NCDslIntent]
+    private val cache = new mutable.HashMap[String, Set[NCDslIntent]]
 
     /**
      *
@@ -41,12 +42,20 @@ object NCIntentDslCompiler extends LazyLogging {
      * @param mdlId
      */
     class FiniteStateMachine(dsl: String, mdlId: String) extends NCIntentDslBaseListener with NCIntentDslBaselCompiler {
+        // Accumulator for parsed intents.
+        private val intents = ArrayBuffer.empty[NCDslIntent]
+
+        // Fragment components.
+        private var fragId: String = _
+
         // Intent components.
-        private var id: String = _
+        private var intentId: String = _
         private var ordered: Boolean = false
-        private val terms = ArrayBuffer.empty[NCDslTerm] // Accumulator for parsed terms.
         private var flowRegex: Option[String] = None
 
+        // Accumulator for parsed terms.
+        private val terms = ArrayBuffer.empty[NCDslTerm]
+
         // Current JSON-based meta.
         private var meta: Map[String, Any] = _
 
@@ -66,14 +75,14 @@ object NCIntentDslCompiler extends LazyLogging {
         /*
          * Shared/common implementation.
          */
-        override def exitUnaryExpr(ctx: Parser.UnaryExprContext): Unit = termInstrs += parseUnaryExpr(ctx.MINUS(), ctx.NOT())(ctx)
-        override def exitMultExpr(ctx: Parser.MultExprContext): Unit = termInstrs += parseMultExpr(ctx.MULT(), ctx.MOD(), ctx.DIV())(ctx)
-        override def exitPlusExpr(ctx: Parser.PlusExprContext): Unit = termInstrs += parsePlusExpr(ctx.PLUS(), ctx.MINUS())(ctx)
-        override def exitCompExpr(ctx: Parser.CompExprContext): Unit = termInstrs += parseCompExpr(ctx.LT(), ctx.GT(), ctx.LTEQ(), ctx.GTEQ())(ctx)
-        override def exitLogExpr(ctx: Parser.LogExprContext): Unit = termInstrs += parseLogExpr(ctx.AND, ctx.OR())(ctx)
-        override def exitEqExpr(ctx: Parser.EqExprContext): Unit = termInstrs += parseEqExpr(ctx.EQ, ctx.NEQ())(ctx)
-        override def exitCallExpr(ctx: Parser.CallExprContext): Unit = termInstrs += parseCallExpr(ctx.FUN_NAME())(ctx)
-        override def exitAtom(ctx: Parser.AtomContext): Unit = termInstrs += parseAtom(ctx.getText)(ctx)
+        override def exitUnaryExpr(ctx: IDP.UnaryExprContext): Unit = termInstrs += parseUnaryExpr(ctx.MINUS(), ctx.NOT())(ctx)
+        override def exitMultExpr(ctx: IDP.MultExprContext): Unit = termInstrs += parseMultExpr(ctx.MULT(), ctx.MOD(), ctx.DIV())(ctx)
+        override def exitPlusExpr(ctx: IDP.PlusExprContext): Unit = termInstrs += parsePlusExpr(ctx.PLUS(), ctx.MINUS())(ctx)
+        override def exitCompExpr(ctx: IDP.CompExprContext): Unit = termInstrs += parseCompExpr(ctx.LT(), ctx.GT(), ctx.LTEQ(), ctx.GTEQ())(ctx)
+        override def exitLogExpr(ctx: IDP.LogExprContext): Unit = termInstrs += parseLogExpr(ctx.AND, ctx.OR())(ctx)
+        override def exitEqExpr(ctx: IDP.EqExprContext): Unit = termInstrs += parseEqExpr(ctx.EQ, ctx.NEQ())(ctx)
+        override def exitCallExpr(ctx: IDP.CallExprContext): Unit = termInstrs += parseCallExpr(ctx.FUN_NAME())(ctx)
+        override def exitAtom(ctx: IDP.AtomContext): Unit = termInstrs += parseAtom(ctx.getText)(ctx)
 
         /**
          *
@@ -85,7 +94,7 @@ object NCIntentDslCompiler extends LazyLogging {
             this.max = max
         }
 
-        override def exitMinMaxShortcut(ctx: Parser.MinMaxShortcutContext): Unit = {
+        override def exitMinMaxShortcut(ctx: IDP.MinMaxShortcutContext): Unit = {
             if (ctx.PLUS() != null)
                 setMinMax(1, Integer.MAX_VALUE)
             else if (ctx.MULT() != null)
@@ -96,20 +105,21 @@ object NCIntentDslCompiler extends LazyLogging {
                 assert(false)
         }
 
-        override def exitMtdRef(ctx: Parser.MtdRefContext): Unit = {
+        override def exitMtdRef(ctx: IDP.MtdRefContext): Unit = {
             if (ctx.javaFqn() != null)
                 refClsName = Some(ctx.javaFqn().getText)
 
             refMtdName = Some(ctx.id().getText)
         }
 
-        override def exitTermId(ctx: Parser.TermIdContext): Unit = termId = ctx.id().getText
-        override def exitTermEq(ctx: Parser.TermEqContext): Unit =  termConv = ctx.TILDA() != null
-        override def exitIntentId(ctx: Parser.IntentIdContext): Unit = id = ctx.id().getText
-        override def exitMetaDecl(ctx: Parser.MetaDeclContext): Unit = meta = U.jsonToScalaMap(ctx.jsonObj().getText)
-        override def exitOrderedDecl(ctx: Parser.OrderedDeclContext): Unit = ordered = ctx.BOOL().getText == "true"
+        override def exitTermId(ctx: IDP.TermIdContext): Unit = termId = ctx.id().getText
+        override def exitTermEq(ctx: IDP.TermEqContext): Unit =  termConv = ctx.TILDA() != null
+        override def exitIntentId(ctx: IDP.IntentIdContext): Unit = intentId = ctx.id().getText
+        override def exitFragId(ctx: IDP.FragIdContext): Unit = fragId = ctx.id().getText
+        override def exitMetaDecl(ctx: IDP.MetaDeclContext): Unit = meta = U.jsonToScalaMap(ctx.jsonObj().getText)
+        override def exitOrderedDecl(ctx: IDP.OrderedDeclContext): Unit = ordered = ctx.BOOL().getText == "true"
 
-        override def exitFlowDecl(ctx: Parser.FlowDeclContext): Unit = {
+        override def exitFlowDecl(ctx: IDP.FlowDeclContext): Unit = {
             implicit val evidence: ParserRuleContext = ctx
 
             if (ctx.qstring() != null) {
@@ -128,7 +138,7 @@ object NCIntentDslCompiler extends LazyLogging {
             }
         }
 
-        override def exitTerm(ctx: Parser.TermContext): Unit = {
+        override def exitTerm(ctx: IDP.TermContext): Unit = {
             implicit val c: ParserRuleContext = ctx
 
             if (min < 0 || min > max)
@@ -138,6 +148,7 @@ object NCIntentDslCompiler extends LazyLogging {
 
             val pred =
                 if (refMtdName != null) { // User-code defined term.
+                    // Closure copies.
                     val clsName = refClsName.orNull
                     val mtdName = refMtdName.orNull
 
@@ -188,7 +199,11 @@ object NCIntentDslCompiler extends LazyLogging {
                     }
 
                 }
-
+                
+            // Check term ID uniqueness.
+            if (terms.exists(t ⇒ t.id != null && t.id == termId))
+                throw newSyntaxError(s"Duplicate term ID: $termId")
+                
             // Add term.
             terms += NCDslTerm(
                 termId,
@@ -205,16 +220,42 @@ object NCIntentDslCompiler extends LazyLogging {
             refMtdName = None
         }
 
+        override def exitFrag(ctx: IDP.FragContext): Unit = {
+            if (FragCache.get(mdlId, fragId).isDefined)
+                throw newSyntaxError(s"Duplicate fragment ID: $fragId")(ctx)
+
+            FragCache.add(mdlId, NCDslFragment(fragId, terms.toList))
+
+            terms.clear()
+        }
+        
+        override def exitIntent(ctx: IDP.IntentContext): Unit = {
+            // Check intent ID uniqueness (only for the current source).
+            if (intents.exists(i ⇒ i.id != null && i.id == intentId))
+                throw newSyntaxError(s"Duplicate intent ID: $termId")(ctx)
+
+            intents += NCDslIntent(
+                dsl,
+                intentId,
+                ordered,
+                if (meta == null) Map.empty else meta,
+                flowRegex,
+                refClsName,
+                refMtdName,
+                terms.toList
+            )
+
+            refClsName = None
+            refMtdName = None
+
+            terms.clear()
+        }
+
         /**
          *
          * @return
          */
-        def getBuiltIntent: NCDslIntent = {
-            require(id != null)
-            require(terms.nonEmpty)
-
-            NCDslIntent(dsl, id, ordered, if (meta == null) Map.empty else meta, flowRegex, refClsName, refMtdName,  terms.toList)
-        }
+        def getBuiltIntents: Set[NCDslIntent] = intents.toSet
         
         override def syntaxError(errMsg: String, srcName: String, line: Int, pos: Int): NCE =
             throw new NCE(mkSyntaxError(errMsg, srcName, line, pos, dsl, mdlId))
@@ -335,30 +376,30 @@ object NCIntentDslCompiler extends LazyLogging {
     ): Set[NCDslIntent] = {
         require(dsl != null)
 
-        val src = dsl.strip()
+        val aDsl = dsl.strip()
 
-        val intent: NCDslIntent = cache.getOrElseUpdate(src, {
+        val intents: Set[NCDslIntent] = cache.getOrElseUpdate(aDsl, {
             // ANTLR4 armature.
-            val lexer = new NCIntentDslLexer(CharStreams.fromString(src))
+            val lexer = new NCIntentDslLexer(CharStreams.fromString(aDsl))
             val tokens = new CommonTokenStream(lexer)
-            val parser = new Parser(tokens)
+            val parser = new IDP(tokens)
 
             // Set custom error handlers.
             lexer.removeErrorListeners()
             parser.removeErrorListeners()
-            lexer.addErrorListener(new CompilerErrorListener(src, mdlId))
-            parser.addErrorListener(new CompilerErrorListener(src, mdlId))
+            lexer.addErrorListener(new CompilerErrorListener(aDsl, mdlId))
+            parser.addErrorListener(new CompilerErrorListener(aDsl, mdlId))
 
             // State automata.
-            val fsm = new FiniteStateMachine(src, mdlId)
+            val fsm = new FiniteStateMachine(aDsl, mdlId)
 
             // Parse the input DSL and walk built AST.
-            (new ParseTreeWalker).walk(fsm, parser.intent())
+            (new ParseTreeWalker).walk(fsm, parser.dsl())
 
             // Return the built intent.
-            fsm.getBuiltIntent
+            fsm.getBuiltIntents
         })
 
-        Set(intent) // TODO
+        intents
     }
 }