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/09 17:43:49 UTC

[incubator-nlpcraft] 01/02: WIP.

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 67255ef6c46eea3a6791fed18c3b5f6c333d769a
Author: Aaron Radzinski <ar...@apache.org>
AuthorDate: Mon Mar 8 16:42:01 2021 -0800

    WIP.
---
 .../intent/impl/NCIntentDslBaselCompiler.scala     | 171 +++++-----------
 .../model/intent/impl/NCIntentDslCompiler.scala    | 224 ++++++++++++++-------
 .../probe/mgrs/deploy/NCDeployManager.scala        |   6 +-
 .../dsl/compiler/NCIntentDslCompilerSpec.scala     |   6 +-
 4 files changed, 209 insertions(+), 198 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/NCIntentDslBaselCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/NCIntentDslBaselCompiler.scala
index 0011b26..f31286e 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/NCIntentDslBaselCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/NCIntentDslBaselCompiler.scala
@@ -419,20 +419,6 @@ trait NCIntentDslBaselCompiler {
             pop1()
         }
 
-        /*
-         * String operations.
-         */
-        def doTrim(): Unit = get1Str() match { case (s, f) ⇒ pushAny(s.trim, f) }
-        def doUppercase(): Unit = get1Str() match { case (s, f) ⇒ pushAny(s.toUpperCase, f) }
-        def doLowercase(): Unit = get1Str() match { case (s, f) ⇒ pushAny(s.toLowerCase, f) }
-        def doIsAlpha(): Unit = get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isAlpha(asString(s)), f) }
-        def doIsNum(): Unit = get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isNumeric(asString(s)), f) }
-        def doIsAlphaNum(): Unit = get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isAlphanumeric(asString(s)), f) }
-        def doIsWhitespace(): Unit = get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isWhitespace(asString(s)), f) }
-        def doIsAlphaSpace(): Unit = get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isAlphaSpace(asString(s)), f) }
-        def doIsAlphaNumSpace(): Unit = get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isAlphanumericSpace(asString(s)), f) }
-        def doIsNumSpace(): Unit = get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isNumericSpace(asString(s)), f) }
-
         def doSplit(): Unit = {
             ensureStack(2)
 
@@ -502,15 +488,6 @@ trait NCIntentDslBaselCompiler {
         /*
          * Metadata operations.
          */
-        def doTokenMeta(): Unit = get1Str() match { case (s, _) ⇒ pushAny(tok.meta(s), true) }
-        def doModelMeta(): Unit = get1Str() match { case (s, _) ⇒ pushAny(tok.getModel.meta(s), false) }
-        def doReqMeta(): Unit = get1Str() match { case (s, _) ⇒ pushAny(termCtx.reqMeta.get(s).orNull, false) }
-        def doSysMeta(): Unit = get1Str() match { case (s, _) ⇒ pushAny(U.sysEnv(s).orNull, false) }
-        def doUserMeta(): Unit = get1Str() match { case (s, _) ⇒ pushAny(termCtx.usrMeta.get(s).orNull, false) }
-        def doConvMeta(): Unit = get1Str() match { case (s, _) ⇒ pushAny(termCtx.convMeta.get(s).orNull, false) }
-        def doCompMeta(): Unit = get1Str() match { case (s, _) ⇒ pushAny(termCtx.compMeta.get(s).orNull, false) }
-        def doIntentMeta(): Unit = get1Str() match { case (s, _) ⇒ pushAny(termCtx.intentMeta.get(s).orNull, false) }
-        def doFragMeta(): Unit = get1Str() match { case (s, _) ⇒ pushAny(termCtx.fragMeta.get(s).orNull, false) }
         def doPartMeta(): Unit = {
             ensureStack(2)
 
@@ -537,44 +514,6 @@ trait NCIntentDslBaselCompiler {
             case (a: JDouble, f) ⇒ pushDouble(a * a, f)
             case x ⇒ throw rtParamTypeError(fun, x, "numeric")
         }
-        def doCeil(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.ceil(a), f) }
-        def doFloor(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.floor(a), f) }
-        def doSignum(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.signum(a), f) }
-        def doAcos(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.acos(a), f) }
-        def doAsin(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.asin(a), f) }
-        def doSin(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.sin(a), f) }
-        def doCos(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.cos(a), f) }
-        def doRint(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.rint(a), f) }
-        def doRound(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushLong(Math.round(a), f) }
-        def doSqrt(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.sqrt(a), f) }
-        def doCbrt(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.cbrt(a), f) }
-        def doAtan(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.atan(a), f) }
-        def doTan(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.tan(a), f) }
-        def doCosh(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.cosh(a), f) }
-        def doSinh(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.sinh(a), f) }
-        def doTanh(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.tanh(a), f) }
-        def doLog(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.log(a), f) }
-        def doLog1p(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.log1p(a), f) }
-        def doLog10(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.log10(a), f) }
-        def doDegrees(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.toDegrees(a), f) }
-        def doRadians(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.toRadians(a), f) }
-        def doExp(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.exp(a), f) }
-        def doExpm1(): Unit = get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.expm1(a), f) }
-        def doRandom(): Unit = pushDouble(Math.random, false)
-        def doPi(): Unit = pushDouble(Math.PI, false)
-        def doEuler(): Unit = pushDouble(Math.E, false)
-        def doPow(): Unit = get2Doubles() match { case (a1: JDouble, a2: JDouble, f) ⇒ pushDouble(Math.pow(a1, a2), f) }
-        def doHypot(): Unit = get2Doubles() match { case (a1: JDouble, a2: JDouble, f) ⇒ pushDouble(Math.hypot(a1, a2), f) }
-        def doAtan2(): Unit = get2Doubles() match { case (a1: JDouble, a2: JDouble, f) ⇒ pushDouble(Math.atan2(a1, a2), f) }
-
-        /*
-         * Date-time operations.
-         */
-        def doYear(): Unit = pushLong(LocalDate.now.getYear,false)
-        def doMonth(): Unit = pushLong(LocalDate.now.getMonthValue,false)
-        def doDayOfMonth(): Unit = pushLong(LocalDate.now.getDayOfMonth,false)
-        def doDayOfWeek(): Unit = pushLong(LocalDate.now.getDayOfWeek.getValue,false)
-        def doDayOfYear(): Unit = pushLong(LocalDate.now.getDayOfYear,false)
 
         def doJson(): Unit = get1Str() match { case (s, f) ⇒ pushAny(U.jsonToJavaMap(asString(s)), f) }
         def doIf(): Unit = {
@@ -638,16 +577,16 @@ trait NCIntentDslBaselCompiler {
 
         fun match {
             // Metadata access.
-            case "meta_token" ⇒ doTokenMeta()
             case "meta_part" ⇒ doPartMeta()
-            case "meta_model" ⇒ doModelMeta()
-            case "meta_intent" ⇒ doIntentMeta()
-            case "meta_req" ⇒ doReqMeta()
-            case "meta_user" ⇒ doUserMeta()
-            case "meta_company" ⇒ doCompMeta()
-            case "meta_sys" ⇒ doSysMeta()
-            case "meta_conv" ⇒ doConvMeta()
-            case "meta_frag" ⇒ doFragMeta()
+            case "meta_token" ⇒ get1Str() match { case (s, _) ⇒ pushAny(tok.meta(s), true) }
+            case "meta_model" ⇒ get1Str() match { case (s, _) ⇒ pushAny(tok.getModel.meta(s), false) }
+            case "meta_intent" ⇒ get1Str() match { case (s, _) ⇒ pushAny(termCtx.intentMeta.get(s).orNull, false) }
+            case "meta_req" ⇒ get1Str() match { case (s, _) ⇒ pushAny(termCtx.reqMeta.get(s).orNull, false) }
+            case "meta_user" ⇒ get1Str() match { case (s, _) ⇒ pushAny(termCtx.usrMeta.get(s).orNull, false) }
+            case "meta_company" ⇒ get1Str() match { case (s, _) ⇒ pushAny(termCtx.compMeta.get(s).orNull, false) }
+            case "meta_sys" ⇒ get1Str() match { case (s, _) ⇒ pushAny(U.sysEnv(s).orNull, false) }
+            case "meta_conv" ⇒ get1Str() match { case (s, _) ⇒ pushAny(termCtx.convMeta.get(s).orNull, false) }
+            case "meta_frag" ⇒ get1Str() match { case (s, _) ⇒ pushAny(termCtx.fragMeta.get(s).orNull, false) }
 
             // Converts JSON to map.
             case "json" ⇒ doJson()
@@ -694,17 +633,17 @@ trait NCIntentDslBaselCompiler {
             case "comp_postcode" ⇒
 
             // String functions.
-            case "trim" ⇒ doTrim()
-            case "strip" ⇒ doTrim()
-            case "uppercase" ⇒ doUppercase()
-            case "lowercase" ⇒ doLowercase()
-            case "is_alpha" ⇒ doIsAlpha()
-            case "is_alphanum" ⇒ doIsAlphaNum()
-            case "is_whitespace" ⇒ doIsWhitespace()
-            case "is_num" ⇒ doIsNum()
-            case "is_numspace" ⇒ doIsNumSpace()
-            case "is_alphaspace" ⇒ doIsAlphaSpace()
-            case "is_alphanumspace" ⇒ doIsAlphaNumSpace()
+            case "trim" ⇒ get1Str() match { case (s, f) ⇒ pushAny(s.trim, f) }
+            case "strip" ⇒ get1Str() match { case (s, f) ⇒ pushAny(s.trim, f) }
+            case "uppercase" ⇒ get1Str() match { case (s, f) ⇒ pushAny(s.toUpperCase, f) }
+            case "lowercase" ⇒ get1Str() match { case (s, f) ⇒ pushAny(s.toLowerCase, f) }
+            case "is_alpha" ⇒ get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isAlpha(asString(s)), f) }
+            case "is_alphanum" ⇒ get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isAlphanumeric(asString(s)), f) }
+            case "is_whitespace" ⇒ get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isWhitespace(asString(s)), f) }
+            case "is_num" ⇒ get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isNumeric(asString(s)), f) }
+            case "is_numspace" ⇒ get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isNumericSpace(asString(s)), f) }
+            case "is_alphaspace" ⇒ get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isAlphaSpace(asString(s)), f) }
+            case "is_alphanumspace" ⇒ get1Str() match { case (s, f) ⇒ pushBool(StringUtils.isAlphanumericSpace(asString(s)), f) }
             case "substring" ⇒
             case "charAt" ⇒
             case "regex" ⇒
@@ -715,35 +654,35 @@ trait NCIntentDslBaselCompiler {
 
             // Math functions.
             case "abs" ⇒ doAbs()
-            case "ceil" ⇒ doCeil()
-            case "floor" ⇒ doFloor()
-            case "rint" ⇒ doRint()
-            case "round" ⇒ doRound()
-            case "signum" ⇒ doSignum()
-            case "sqrt" ⇒ doSqrt()
-            case "cbrt" ⇒ doCbrt()
-            case "pi" ⇒ doPi()
-            case "euler" ⇒ doEuler()
-            case "acos" ⇒ doAcos()
-            case "asin" ⇒ doAsin()
-            case "atan" ⇒ doAtan()
-            case "cos" ⇒ doCos()
-            case "sin" ⇒ doSin()
-            case "tan" ⇒ doTan()
-            case "cosh" ⇒ doCosh()
-            case "sinh" ⇒ doSinh()
-            case "tanh" ⇒ doTanh()
-            case "atn2" ⇒ doAtan2()
-            case "degrees" ⇒ doDegrees()
-            case "radians" ⇒ doRadians()
-            case "exp" ⇒ doExp()
-            case "expm1" ⇒ doExpm1()
-            case "hypot" ⇒ doHypot()
-            case "log" ⇒ doLog()
-            case "log10" ⇒ doLog10()
-            case "log1p" ⇒ doLog1p()
-            case "pow" ⇒ doPow()
-            case "rand" ⇒ doRandom()
+            case "ceil" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.ceil(a), f) }
+            case "floor" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.floor(a), f) }
+            case "rint" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.rint(a), f) }
+            case "round" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushLong(Math.round(a), f) }
+            case "signum" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.signum(a), f) }
+            case "sqrt" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.sqrt(a), f) }
+            case "cbrt" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.cbrt(a), f) }
+            case "pi" ⇒ pushDouble(Math.PI, false)
+            case "euler" ⇒ pushDouble(Math.E, false)
+            case "acos" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.acos(a), f) }
+            case "asin" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.asin(a), f) }
+            case "atan" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.atan(a), f) }
+            case "cos" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.cos(a), f) }
+            case "sin" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.sin(a), f) }
+            case "tan" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.tan(a), f) }
+            case "cosh" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.cosh(a), f) }
+            case "sinh" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.sinh(a), f) }
+            case "tanh" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.tanh(a), f) }
+            case "atn2" ⇒ get2Doubles() match { case (a1: JDouble, a2: JDouble, f) ⇒ pushDouble(Math.atan2(a1, a2), f) }
+            case "degrees" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.toDegrees(a), f) }
+            case "radians" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.toRadians(a), f) }
+            case "exp" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.exp(a), f) }
+            case "expm1" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.expm1(a), f) }
+            case "hypot" ⇒ get2Doubles() match { case (a1: JDouble, a2: JDouble, f) ⇒ pushDouble(Math.hypot(a1, a2), f) }
+            case "log" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.log(a), f) }
+            case "log10" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.log10(a), f) }
+            case "log1p" ⇒ get1Double() match { case (a: JDouble, f) ⇒ pushDouble(Math.log1p(a), f) }
+            case "pow" ⇒ get2Doubles() match { case (a1: JDouble, a2: JDouble, f) ⇒ pushDouble(Math.pow(a1, a2), f) }
+            case "rand" ⇒ pushDouble(Math.random, false)
             case "square" ⇒ doSquare()
 
             // Collection functions.
@@ -777,18 +716,18 @@ trait NCIntentDslBaselCompiler {
             case "sum" ⇒
 
             // Date-time functions.
-            case "year" ⇒ doYear() // 2021.
-            case "month" ⇒ doMonth() // 1 ... 12.
-            case "day_of_month" ⇒ doDayOfMonth() // 1 ... 31.
-            case "day_of_week" ⇒ doDayOfWeek()
-            case "day_of_year" ⇒ doDayOfYear()
+            case "year" ⇒ pushLong(LocalDate.now.getYear,false) // 2021.
+            case "month" ⇒ pushLong(LocalDate.now.getMonthValue,false) // 1 ... 12.
+            case "day_of_month" ⇒ pushLong(LocalDate.now.getDayOfMonth,false) // 1 ... 31.
+            case "day_of_week" ⇒ pushLong(LocalDate.now.getDayOfWeek.getValue,false)
+            case "day_of_year" ⇒ pushLong(LocalDate.now.getDayOfYear,false)
             case "hour" ⇒
             case "minute" ⇒
             case "second" ⇒
             case "week_of_month" ⇒
             case "week_of_year" ⇒
             case "quarter" ⇒
-            case "now" ⇒ // Epoc time.
+            case "now" ⇒ pushLong(System.currentTimeMillis(),false) // Epoc time.
 
             case _ ⇒ throw rtUnknownFunError(fun) // Assertion.
         }
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/NCIntentDslCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/NCIntentDslCompiler.scala
index 1fdbd57..691af29 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/NCIntentDslCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/impl/NCIntentDslCompiler.scala
@@ -34,8 +34,9 @@ import scala.collection.mutable
 import scala.collection.mutable.ArrayBuffer
 
 object NCIntentDslCompiler extends LazyLogging {
-    // Compiler cache.
-    private val cache = new mutable.HashMap[String, Set[NCDslIntent]]
+    // Compiler caches.
+    private val intentCache = new mutable.HashMap[String, Set[NCDslIntent]]
+    private val synCache = new mutable.HashMap[String, NCDslSynonym]
 
     /**
      *
@@ -76,12 +77,19 @@ object NCIntentDslCompiler extends LazyLogging {
          * Shared/common implementation.
          */
         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)
 
         /**
@@ -104,11 +112,11 @@ object NCIntentDslCompiler extends LazyLogging {
             else
                 assert(false)
         }
-    
+
         override def exitMinMaxRange(ctx: IDP.MinMaxRangeContext): Unit = {
             val minStr = ctx.getChild(1).getText.trim
             val maxStr = ctx.getChild(3).getText.trim
-        
+
             try
                 setMinMax(java.lang.Integer.parseInt(minStr), java.lang.Integer.parseInt(maxStr))
             catch {
@@ -126,28 +134,31 @@ object NCIntentDslCompiler extends LazyLogging {
 
         override def exitTermId(ctx: IDP.TermIdContext): Unit = {
             termId = ctx.id().getText
-    
+
             if (terms.exists(t ⇒ t.id === termId))
-                throw newSyntaxError(s"Duplicate term ID: $termId")(ctx.id())
+                throw newSyntaxError(s"Duplicate intent term ID: $termId")(ctx.id())
         }
-    
+
         override def exitIntentId(ctx: IDP.IntentIdContext): Unit = {
             intentId = ctx.id().getText
-    
+
             if (intents.exists(i ⇒ i.id != null && i.id == intentId))
                 throw newSyntaxError(s"Duplicate intent ID: $intentId")(ctx.id())
         }
-    
+
         override def exitFragId(ctx: IDP.FragIdContext): Unit = {
             fragId = ctx.id().getText
-    
+
             if (FragCache.get(mdlId, fragId).isDefined)
                 throw newSyntaxError(s"Duplicate fragment ID: $fragId")(ctx.id())
         }
 
-        override def exitTermEq(ctx: IDP.TermEqContext): Unit =  termConv = ctx.TILDA() != null
+        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)
+
         override def exitOrderedDecl(ctx: IDP.OrderedDeclContext): Unit = ordered = ctx.BOOL().getText == "true"
 
         override def exitFragRef(ctx: IDP.FragRefContext): Unit = {
@@ -158,7 +169,7 @@ object NCIntentDslCompiler extends LazyLogging {
                     val meta = if (fragMeta == null) Map.empty[String, Any] else fragMeta
 
                     for (fragTerm ← frag.terms)
-                         if (terms.exists(t ⇒ t.id === fragTerm.id))
+                        if (terms.exists(t ⇒ t.id === fragTerm.id))
                             throw newSyntaxError(s"Duplicate term ID '${fragTerm.id.get}' in fragment '$id'.")(ctx.id())
                         else
                             terms += fragTerm.cloneWithFragMeta(meta)
@@ -261,7 +272,7 @@ object NCIntentDslCompiler extends LazyLogging {
                         val stack = new mutable.ArrayStack[NCDslTermRetVal]()
 
                         // Execute all instructions.
-                        instrs.foreach(_(tok, stack, termCtx))
+                        instrs.foreach(_ (tok, stack, termCtx))
 
                         // Pop final result from stack.
                         val x = stack.pop()
@@ -273,7 +284,7 @@ object NCIntentDslCompiler extends LazyLogging {
                     }
 
                 }
-                
+
             // Add term.
             terms += NCDslTerm(
                 Option(termId),
@@ -296,7 +307,7 @@ object NCIntentDslCompiler extends LazyLogging {
 
             terms.clear()
         }
-        
+
         override def exitIntent(ctx: IDP.IntentContext): Unit = {
             intents += NCDslIntent(
                 dsl,
@@ -319,10 +330,17 @@ object NCIntentDslCompiler extends LazyLogging {
          *
          * @return
          */
-        def getBuiltIntents: Set[NCDslIntent] = intents.toSet
-        
+        def getCompiledIntents: Set[NCDslIntent] = intents.toSet
+
+        /**
+         *
+         * @return
+         */
+        def getCompiledSynonym: NCDslSynonym = ???
+
         override def syntaxError(errMsg: String, srcName: String, line: Int, pos: Int): NCE =
             throw new NCE(mkSyntaxError(errMsg, srcName, line, pos, dsl, mdlId))
+
         override def runtimeError(errMsg: String, srcName: String, line: Int, pos: Int, cause: Exception = null): NCE =
             throw new NCE(mkRuntimeError(errMsg, srcName, line, pos, dsl, mdlId), cause)
     }
@@ -345,15 +363,15 @@ object NCIntentDslCompiler extends LazyLogging {
         mdlId: String): String = mkError("syntax", msg, srcName, line, charPos, dsl, mdlId)
 
     /**
-      *
-      * @param msg
-      * @param dsl
-      * @param mdlId
-      * @param srcName
-      * @param line
-      * @param charPos
-      * @return
-      */
+     *
+     * @param msg
+     * @param dsl
+     * @param mdlId
+     * @param srcName
+     * @param line
+     * @param charPos
+     * @return
+     */
     private def mkRuntimeError(
         msg: String,
         srcName: String,
@@ -379,13 +397,13 @@ object NCIntentDslCompiler extends LazyLogging {
             case s: String if s.last == '.' ⇒ s
             case s: String ⇒ s + '.'
         }
-        
-        s"Intent DSL $kind error in '$srcName' at line $line:${charPos + 1} - $aMsg\n" +
-        s"  |-- ${c("Model:")}    $mdlId\n" +
-        s"  |-- ${c("Line:")}     $dslPtr\n" +
-        s"  +-- ${c("Position:")} $posPtr"
+
+        s"DSL $kind error in '$srcName' at line $line:${charPos + 1} - $aMsg\n" +
+            s"  |-- ${c("Model:")}    $mdlId\n" +
+            s"  |-- ${c("Line:")}     $dslPtr\n" +
+            s"  +-- ${c("Position:")} $posPtr"
     }
-    
+
     /**
      * Custom error handler.
      *
@@ -411,15 +429,15 @@ object NCIntentDslCompiler extends LazyLogging {
             e: RecognitionException): Unit =
             throw new NCE(mkSyntaxError(msg, recog.getInputStream.getSourceName, line, charPos - 1, dsl, mdlId))
     }
-    
+
     /**
-      *
-      * @param dsl
-      * @param mdlId
-      * @param srcName
-      * @return
-      */
-    private def antlr4(
+     *
+     * @param dsl
+     * @param mdlId
+     * @param srcName
+     * @return
+     */
+    private def parseIntents(
         dsl: String,
         mdlId: String,
         srcName: String
@@ -427,61 +445,115 @@ object NCIntentDslCompiler extends LazyLogging {
         require(dsl != null)
         require(mdlId != null)
         require(srcName != null)
-    
-        val aDsl = dsl.strip()
-    
-        val intents: Set[NCDslIntent] = cache.getOrElseUpdate(aDsl, {
-            // ANTLR4 armature.
-            val lexer = new NCIntentDslLexer(CharStreams.fromString(aDsl, srcName))
-            val tokens = new CommonTokenStream(lexer)
-            val parser = new IDP(tokens)
-        
-            // Set custom error handlers.
-            lexer.removeErrorListeners()
-            parser.removeErrorListeners()
-            lexer.addErrorListener(new CompilerErrorListener(aDsl, mdlId))
-            parser.addErrorListener(new CompilerErrorListener(aDsl, mdlId))
-        
-            // State automata.
-            val fsm = new FiniteStateMachine(aDsl, mdlId)
-        
+
+        val x = dsl.strip()
+
+        val intents: Set[NCDslIntent] = intentCache.getOrElseUpdate(x, {
+            val (fsm, parser) = antlr4Armature(x, mdlId)
+
             // Parse the input DSL and walk built AST.
             (new ParseTreeWalker).walk(fsm, parser.dsl())
-        
-            // Return the built intent.
-            fsm.getBuiltIntents
+
+            // Return the compiled intents.
+            fsm.getCompiledIntents
         })
-    
+
         intents
     }
-    
+
     /**
-      * Compiles inline (supplied) fragments and/or intents from given file. Note that fragments are
-      * accumulated in a static map keyed by model ID. Only intents are returned, if any.
-      *
-      * @param filePath *.nc DSL file to compile.
-      * @param mdlId ID of the model *.nc file belongs to.
-      * @return
-      */
+     *
+     * @param dsl
+     * @param mdlId
+     * @return
+     */
+    private def parseSynonym(
+        dsl: String,
+        mdlId: String
+    ): NCDslSynonym = {
+        require(dsl != null)
+        require(mdlId != null)
+
+        val x = dsl.strip()
+
+        val syn: NCDslSynonym = synCache.getOrElseUpdate(x, {
+            val (fsm, parser) = antlr4Armature(x, mdlId)
+
+            // Parse the input DSL and walk built AST.
+            (new ParseTreeWalker).walk(fsm, parser.synonym())
+
+            // Return the compiled synonym.
+            fsm.getCompiledSynonym
+        })
+
+        syn
+    }
+
+    /**
+     *
+     * @param dsl
+     * @param mdlId
+     * @param srcName
+     * @return
+     */
+    private def antlr4Armature(
+        dsl: String,
+        mdlId: String,
+        srcName: String = "<inline>"
+    ): (FiniteStateMachine, IDP) = {
+        val lexer = new NCIntentDslLexer(CharStreams.fromString(dsl, srcName))
+        val tokens = new CommonTokenStream(lexer)
+        val parser = new IDP(tokens)
+
+        // Set custom error handlers.
+        lexer.removeErrorListeners()
+        parser.removeErrorListeners()
+        lexer.addErrorListener(new CompilerErrorListener(dsl, mdlId))
+        parser.addErrorListener(new CompilerErrorListener(dsl, mdlId))
+
+        // State automata + it's parser.
+        new FiniteStateMachine(dsl, mdlId) → parser
+    }
+
+    /**
+     * Compiles inline (supplied) fragments and/or intents from given file. Note that fragments are
+     * accumulated in a static map keyed by model ID. Only intents are returned, if any.
+     *
+     * @param filePath *.nc intent DSL file to compile.
+     * @param mdlId ID of the model *.nc file belongs to.
+     * @return
+     */
     @throws[NCE]
-    def compileIntent(
+    def compileIntents(
         filePath: Path,
         mdlId: String
-    ): Set[NCDslIntent] = antlr4(U.readFile(filePath.toFile).mkString("\n"), mdlId, filePath.getFileName.toString)
-    
+    ): Set[NCDslIntent] = parseIntents(U.readFile(filePath.toFile).mkString("\n"), mdlId, filePath.getFileName.toString)
+
     /**
      * Compiles inline (supplied) fragments and/or intents. Note that fragments are accumulated in a static
      * map keyed by model ID. Only intents are returned, if any.
      *
-     * @param dsl DSL to compile.
+     * @param dsl Intent DSL to compile.
      * @param mdlId ID of the model DSL belongs to.
      * @param srcName Optional source name.
      * @return
      */
     @throws[NCE]
-    def compileIntent(
+    def compileIntents(
         dsl: String,
         mdlId: String,
         srcName: String = "<inline>"
-    ): Set[NCDslIntent] = antlr4(dsl, mdlId, srcName)
+    ): Set[NCDslIntent] = parseIntents(dsl, mdlId, srcName)
+
+    /**
+     *
+     * @param dsl Synonym DSL to compile.
+     * @param mdlId ID of the model DSL belongs to.
+     * @return
+     */
+    @throws[NCE]
+    def compileSynonym(
+        dsl: String,
+        mdlId: String
+    ): NCDslSynonym = parseSynonym(dsl, mdlId)
 }
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala
index f470529..e63aceb 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala
@@ -1473,7 +1473,7 @@ object NCDeployManager extends NCService with DecorateAsScala {
             val mStr = method2Str(m)
 
             // Process inline intent declarations by @NCIntent annotation.
-            for (ann ← m.getAnnotationsByType(CLS_INTENT); intent ← NCIntentDslCompiler.compileIntent(ann.value(), mdl.getId, mStr))
+            for (ann ← m.getAnnotationsByType(CLS_INTENT); intent ← NCIntentDslCompiler.compileIntents(ann.value(), mdl.getId, mStr))
                 intents += (intent → prepareCallback(m, mdl, intent))
     
             // Process intent references from @NCIntentRef annotation.
@@ -1485,7 +1485,7 @@ object NCDeployManager extends NCService with DecorateAsScala {
                         val compiledIntents = adapter
                             .getIntents
                             .asScala
-                            .flatMap(NCIntentDslCompiler.compileIntent(_, mdl.getId, mStr))
+                            .flatMap(NCIntentDslCompiler.compileIntents(_, mdl.getId, mStr))
             
                         U.getDups(compiledIntents.toSeq.map(_.id)) match {
                             case ids if ids.nonEmpty ⇒
@@ -1554,7 +1554,7 @@ object NCDeployManager extends NCService with DecorateAsScala {
                     val distinct = seqSeq.map(_.distinct).distinct
 
                     for (ann ← intAnns) {
-                        for (intent ← NCIntentDslCompiler.compileIntent(ann.value(), mdlId, mStr))
+                        for (intent ← NCIntentDslCompiler.compileIntents(ann.value(), mdlId, mStr))
                             samples += (intent.id → distinct)
                     }
                     for (ann ← refAnns)
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/dsl/compiler/NCIntentDslCompilerSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/dsl/compiler/NCIntentDslCompilerSpec.scala
index a7b2d95..685ea43 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/dsl/compiler/NCIntentDslCompilerSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/dsl/compiler/NCIntentDslCompilerSpec.scala
@@ -35,7 +35,7 @@ class NCIntentDslCompilerSpec {
      */
     private def checkCompileOk(dsl: String): Unit =
         try {
-            NCIntentDslCompiler.compileIntent(dsl, MODEL_ID)
+            NCIntentDslCompiler.compileIntents(dsl, MODEL_ID)
 
             assert(true)
         }
@@ -49,7 +49,7 @@ class NCIntentDslCompilerSpec {
       */
     private def checkPathCompileOk(path: Path): Unit =
         try {
-            NCIntentDslCompiler.compileIntent(path, MODEL_ID)
+            NCIntentDslCompiler.compileIntents(path, MODEL_ID)
             
             assert(true)
         }
@@ -63,7 +63,7 @@ class NCIntentDslCompilerSpec {
      */
     private def checkCompileError(txt: String): Unit =
         try {
-            NCIntentDslCompiler.compileIntent(txt, MODEL_ID)
+            NCIntentDslCompiler.compileIntents(txt, MODEL_ID)
 
             assert(false)
         } catch {