This is an automated email from the ASF dual-hosted git repository. aradzinski pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git
commit da438d47189c4b749fc8410b0fcdead1229bcc51 Author: Aaron Radzinski <[email protected]> AuthorDate: Mon Mar 22 17:33:03 2021 -0700 WIP. --- .../nlpcraft/model/intent/NCIdlContext.scala | 7 +- ...IdlTokenPredicate.scala => NCIdlFunction.scala} | 2 +- .../nlpcraft/model/intent/NCIdlSynonym.scala | 4 +- .../apache/nlpcraft/model/intent/NCIdlTerm.scala | 7 +- .../model/intent/compiler/NCIdlCompiler.scala | 87 ++++++++++++++++------ .../model/intent/solver/NCIntentSolverEngine.scala | 4 +- .../nlpcraft/probe/mgrs/NCProbeSynonymChunk.scala | 4 +- 7 files changed, 82 insertions(+), 33 deletions(-) diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlContext.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlContext.scala index 1d09238..32fa895 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlContext.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlContext.scala @@ -19,6 +19,9 @@ package org.apache.nlpcraft.model.intent import org.apache.nlpcraft.common.ScalaMeta import org.apache.nlpcraft.model.NCRequest +import org.apache.nlpcraft.model.intent.compiler.NCIdlStackItem + +import scala.collection.mutable /** * @@ -26,11 +29,13 @@ import org.apache.nlpcraft.model.NCRequest * @param convMeta Conversation metadata. * @param fragMeta Optional fragment (argument) metadata passed during intent fragment reference. * @param req Server request holder. + * @param vars Variable storage. */ case class NCIdlContext( intentMeta: ScalaMeta = Map.empty[String, Object], convMeta: ScalaMeta = Map.empty[String, Object], fragMeta: ScalaMeta = Map.empty[String, Object], - req: NCRequest + req: NCRequest, + vars: mutable.Map[String, NCIdlStackItem] ) diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlTokenPredicate.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlFunction.scala similarity index 86% rename from nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlTokenPredicate.scala rename to nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlFunction.scala index d585a8a..a876960 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlTokenPredicate.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlFunction.scala @@ -22,4 +22,4 @@ import org.apache.nlpcraft.model.NCToken /** * */ -trait NCIdlTokenPredicate extends ((NCToken, NCIdlContext) ⇒ (Boolean /* Predicate. */ , Int /* How many times a token was used. */ )) +trait NCIdlFunction[T] extends ((NCToken, NCIdlContext) ⇒ (T , Int /* How many times a token was used. */ )) diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlSynonym.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlSynonym.scala index 4abe52a..c092801 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlSynonym.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlSynonym.scala @@ -17,8 +17,6 @@ package org.apache.nlpcraft.model.intent -import org.apache.nlpcraft.model.NCToken - /** * DSl synonym. * @@ -28,7 +26,7 @@ import org.apache.nlpcraft.model.NCToken case class NCIdlSynonym( origin: String, alias: Option[String], - pred: NCIdlTokenPredicate, + pred: NCIdlFunction[Boolean], ) { require(origin != null) require(pred != null) diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlTerm.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlTerm.scala index 5e24e8c..8d33c1a 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlTerm.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCIdlTerm.scala @@ -24,7 +24,8 @@ import org.apache.nlpcraft.common._ * * @param idl * @param id Optional ID of this term. - * @param pred + * @param decls Term optional declarations. + * @param pred Term predicate. * @param min * @param max * @param conv @@ -33,7 +34,8 @@ import org.apache.nlpcraft.common._ case class NCIdlTerm( idl: String, id: Option[String], - pred: NCIdlTokenPredicate, + decls: List[NCIdlFunction[Object]], + pred: NCIdlFunction[Boolean], min: Int, max: Int, conv: Boolean, @@ -51,6 +53,7 @@ case class NCIdlTerm( NCIdlTerm( idl, id, + decls, pred, min, max, diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompiler.scala index a49a71c..356288f 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompiler.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompiler.scala @@ -22,10 +22,10 @@ import org.antlr.v4.runtime.tree.ParseTreeWalker import org.antlr.v4.runtime._ import org.antlr.v4.runtime.{ParserRuleContext ⇒ PRC} import org.apache.nlpcraft.common._ -import org.apache.nlpcraft.model.intent.compiler.antlr4.{NCIdlBaseListener, NCIdlLexer, NCIdlParser ⇒ IDP} +import org.apache.nlpcraft.model.intent.compiler.antlr4.{NCIdlBaseListener, NCIdlLexer, NCIdlParser, NCIdlParser ⇒ IDP} import org.apache.nlpcraft.model.intent.compiler.{NCIdlCompilerGlobal ⇒ Global} import org.apache.nlpcraft.model._ -import org.apache.nlpcraft.model.intent.{NCIdlContext, NCIdlIntent, NCIdlSynonym, NCIdlTerm, NCIdlTokenPredicate} +import org.apache.nlpcraft.model.intent.{NCIdlContext, NCIdlIntent, NCIdlSynonym, NCIdlTerm, NCIdlFunction} import java.io._ import java.net._ @@ -71,6 +71,7 @@ object NCIdlCompiler extends LazyLogging { private val terms = ArrayBuffer.empty[NCIdlTerm] // Currently term. + private var vars = mutable.HashMap.empty[String, NCIdlFunction[Object]] private var termId: String = _ private var termConv: Boolean = _ private var min = 1 @@ -81,7 +82,7 @@ object NCIdlCompiler extends LazyLogging { private var refMtdName: Option[String] = None // List of instructions for the current expression. - private var instrs = mutable.Buffer.empty[I] + private var expr = mutable.Buffer.empty[I] /** @@ -99,14 +100,14 @@ object NCIdlCompiler extends LazyLogging { /* * Shared/common implementation. */ - override def exitUnaryExpr(ctx: IDP.UnaryExprContext): Unit = instrs += parseUnaryExpr(ctx.MINUS(), ctx.NOT())(ctx) - override def exitMultDivModExpr(ctx: IDP.MultDivModExprContext): Unit = instrs += parseMultDivModExpr(ctx.MULT(), ctx.MOD(), ctx.DIV())(ctx) - override def exitPlusMinusExpr(ctx: IDP.PlusMinusExprContext): Unit = instrs += parsePlusMinusExpr(ctx.PLUS(), ctx.MINUS())(ctx) - override def exitCompExpr(ctx: IDP.CompExprContext): Unit = instrs += parseCompExpr(ctx.LT(), ctx.GT(), ctx.LTEQ(), ctx.GTEQ())(ctx) - override def exitAndOrExpr(ctx: IDP.AndOrExprContext): Unit = instrs += parseAndOrExpr(ctx.AND, ctx.OR())(ctx) - override def exitEqNeqExpr(ctx: IDP.EqNeqExprContext): Unit = instrs += parseEqNeqExpr(ctx.EQ, ctx.NEQ())(ctx) - override def exitCallExpr(ctx: IDP.CallExprContext): Unit = instrs += parseCallExpr(ctx.FUN_NAME())(ctx) - override def exitAtom(ctx: IDP.AtomContext): Unit = instrs += parseAtom(ctx.getText)(ctx) + override def exitUnaryExpr(ctx: IDP.UnaryExprContext): Unit = expr += parseUnaryExpr(ctx.MINUS(), ctx.NOT())(ctx) + override def exitMultDivModExpr(ctx: IDP.MultDivModExprContext): Unit = expr += parseMultDivModExpr(ctx.MULT(), ctx.MOD(), ctx.DIV())(ctx) + override def exitPlusMinusExpr(ctx: IDP.PlusMinusExprContext): Unit = expr += parsePlusMinusExpr(ctx.PLUS(), ctx.MINUS())(ctx) + override def exitCompExpr(ctx: IDP.CompExprContext): Unit = expr += parseCompExpr(ctx.LT(), ctx.GT(), ctx.LTEQ(), ctx.GTEQ())(ctx) + override def exitAndOrExpr(ctx: IDP.AndOrExprContext): Unit = expr += parseAndOrExpr(ctx.AND, ctx.OR())(ctx) + override def exitEqNeqExpr(ctx: IDP.EqNeqExprContext): Unit = expr += parseEqNeqExpr(ctx.EQ, ctx.NEQ())(ctx) + override def exitCallExpr(ctx: IDP.CallExprContext): Unit = expr += parseCallExpr(ctx.FUN_NAME())(ctx) + override def exitAtom(ctx: IDP.AtomContext): Unit = expr += parseAtom(ctx.getText)(ctx) override def exitTermEq(ctx: IDP.TermEqContext): Unit = termConv = ctx.TILDA() != null override def exitFragMeta(ctx: IDP.FragMetaContext): Unit = fragMeta = U.jsonToScalaMap(ctx.jsonObj().getText) override def exitMetaDecl(ctx: IDP.MetaDeclContext): Unit = intentMeta = U.jsonToScalaMap(ctx.jsonObj().getText) @@ -115,7 +116,7 @@ object NCIdlCompiler extends LazyLogging { override def exitAlias(ctx: IDP.AliasContext): Unit = alias = ctx.id().getText override def enterCallExpr(ctx: IDP.CallExprContext): Unit = - instrs += ((_, stack: NCIdlStack, _) ⇒ stack.push(stack.PLIST_MARKER)) + expr += ((_, stack: NCIdlStack, _) ⇒ stack.push(stack.PLIST_MARKER)) /** * @@ -127,6 +128,34 @@ object NCIdlCompiler extends LazyLogging { this.max = max } + override def exitVarRef(ctx: NCIdlParser.VarRefContext): Unit = { + + } + + override def exitVarDecl(ctx: NCIdlParser.VarDeclContext): Unit = { + val varName = ctx.id().getText + + if (vars.contains(varName)) + throw newSyntaxError(s"Duplicate variable: $varName")(ctx) + + vars += varName + + val fun = exprToFunction[Object]("Variable declaration", _ ⇒ true, x ⇒ x)(ctx) + + val instr = (tok: NCToken, ctx: NCIdlContext) ⇒ { + val (res, tokUses) = fun(tok, ctx) + + (null, 0) + } + + + + + + + expr.clear() + } + override def exitMinMaxShortcut(ctx: IDP.MinMaxShortcutContext): Unit = { if (ctx.PLUS() != null) setMinMax(1, MINMAX_MAX) @@ -178,9 +207,9 @@ object NCIdlCompiler extends LazyLogging { override def exitSynonym(ctx: IDP.SynonymContext): Unit = { implicit val evidence: PRC = ctx - val pred = instrToPredicate("Synonym") + val pred = exprToFunction("Synonym", isBool, asBool) val capture = alias - val wrapper: NCIdlTokenPredicate = (tok: NCToken, ctx: NCIdlContext) ⇒ { + val wrapper: NCIdlFunction[Boolean] = (tok: NCToken, ctx: NCIdlContext) ⇒ { val (res, tokUses) = pred(tok, ctx) // Store predicate's alias, if any, in token metadata if this token satisfies this predicate. @@ -202,7 +231,7 @@ object NCIdlCompiler extends LazyLogging { synonym = NCIdlSynonym(origin, Option(alias), wrapper) alias = null - instrs.clear() + expr.clear() } override def exitFragId(ctx: IDP.FragIdContext): Unit = { @@ -254,7 +283,7 @@ object NCIdlCompiler extends LazyLogging { if (max < 1) throw newSyntaxError(s"Invalid intent term max quantifiers: $max (must be max >= 1).")(ctx.minMax()) - val pred: NCIdlTokenPredicate = if (refMtdName.isDefined) { // User-code defined term. + val pred: NCIdlFunction[Boolean] = if (refMtdName.isDefined) { // User-code defined term. // Closure copies. val clsName = refClsName.orNull val mtdName = refMtdName.orNull @@ -289,7 +318,7 @@ object NCIdlCompiler extends LazyLogging { } } else // IDL term. - instrToPredicate("Intent term")(ctx.expr()) + exprToFunction("Intent term", isBool, asBool)(ctx.expr()) // Add term. terms += NCIdlTerm( @@ -304,7 +333,8 @@ object NCIdlCompiler extends LazyLogging { // Reset term vars. setMinMax(1, 1) termId = null - instrs.clear() + expr.clear() + vars.clear() refClsName = None refMtdName = None } @@ -312,12 +342,23 @@ object NCIdlCompiler extends LazyLogging { /** * * @param subj + * @param check + * @param cast + * @param ctx + * @tparam T * @return */ - private def instrToPredicate(subj: String)(implicit ctx: PRC): NCIdlTokenPredicate = { + private def exprToFunction[T]( + subj: String, + check: Object ⇒ Boolean, + cast: Object ⇒ T + ) + ( + implicit ctx: PRC + ): NCIdlFunction[T] = { val code = mutable.Buffer.empty[I] - code ++= instrs + code ++= expr (tok: NCToken, termCtx: NCIdlContext) ⇒ { val stack = new S() @@ -329,10 +370,10 @@ object NCIdlCompiler extends LazyLogging { val x = stack.pop()() val v = x.value - if (!isBool(v)) - throw newRuntimeError(s"$subj did not return boolean value: ${ctx.getText}") + if (!check(v)) + throw newRuntimeError(s"$subj returned value of unexpected type '$v' in: ${ctx.getText}") - (asBool(v), x.tokUse) + (cast(v), x.tokUse) } } diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala index 99f8576..6cd92b5 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala @@ -26,6 +26,7 @@ import org.apache.nlpcraft.model.impl.NCTokenLogger import org.apache.nlpcraft.model.{NCContext, NCDialogFlowItem, NCIntentMatch, NCResult, NCToken} import org.apache.nlpcraft.probe.mgrs.dialogflow.NCDialogFlowManager import org.apache.nlpcraft.model.impl.NCTokenPimp._ +import org.apache.nlpcraft.model.intent.compiler.NCIdlStackItem import org.apache.nlpcraft.model.intent.{NCIdlContext, NCIdlIntent, NCIdlTerm} import java.util.function.Function @@ -494,7 +495,8 @@ object NCIntentSolverEngine extends LazyLogging with NCOpenCensusTrace { val termCtx = NCIdlContext( intentMeta = intent.meta, convMeta = if (x.isEmpty) Map.empty[String, Object] else x.asScala.toMap[String, Object], - req = ctx.getRequest + req = ctx.getRequest, + vars = mutable.HashMap.empty[String, NCIdlStackItem] ) // Check terms. diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/NCProbeSynonymChunk.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/NCProbeSynonymChunk.scala index cefb16a..ebc1d8e 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/NCProbeSynonymChunk.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/NCProbeSynonymChunk.scala @@ -17,7 +17,7 @@ package org.apache.nlpcraft.probe.mgrs -import org.apache.nlpcraft.model.intent.NCIdlTokenPredicate +import org.apache.nlpcraft.model.intent.NCIdlFunction import org.apache.nlpcraft.probe.mgrs.NCProbeSynonymChunkKind._ import java.util.regex.Pattern @@ -39,7 +39,7 @@ case class NCProbeSynonymChunk( wordStem: String = null, // Only for kind == TEXT. posTag: String = null, regex: Pattern = null, - idlPred: NCIdlTokenPredicate = null + idlPred: NCIdlFunction = null ) { require(origText != null) require(kind != null)
