diff --git a/packages/lu/src/parser/lufile/visitor.js b/packages/lu/src/parser/lufile/visitor.js index 66f3dfdfc..3ef481f7e 100644 --- a/packages/lu/src/parser/lufile/visitor.js +++ b/packages/lu/src/parser/lufile/visitor.js @@ -1,6 +1,7 @@ const lp = require('./generated/LUFileParser').LUFileParser; const LUISObjNameEnum = require('./../utils/enums/luisobjenum'); const InvalidCharsInIntentOrEntityName = require('./../utils/enums/invalidchars').InvalidCharsInIntentOrEntityName; +const EscapeCharsInUtterance = require('./../utils/enums/escapechars').EscapeCharsInUtterance; class Visitor { /** @@ -20,6 +21,12 @@ class Visitor { utterance = this.recurselyResolveTokenizedUtterance(tokUtt, entities, errorMsgs, utterance.trimLeft()); break; } + case lp.ESCAPE_CHARACTER: { + let escapeCharacters = innerNode.getText(); + let escapedUtterace = escapeCharacters.length > 1 && EscapeCharsInUtterance.includes(escapeCharacters[1]) ? escapeCharacters.slice(1) : escapeCharacters; + utterance = utterance.concat(escapedUtterace); + break; + } default: { utterance = utterance.concat(innerNode.getText()); break; diff --git a/packages/lu/src/parser/utils/enums/escapechars.js b/packages/lu/src/parser/utils/enums/escapechars.js new file mode 100644 index 000000000..0dc5aa636 --- /dev/null +++ b/packages/lu/src/parser/utils/enums/escapechars.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + // Escape chars in utterance +module.exports = { + EscapeCharsInUtterance: ['{', '}', '\\'] +}; \ No newline at end of file diff --git a/packages/lu/test/parser/lufile/parseFileContents.parseFile.test.js b/packages/lu/test/parser/lufile/parseFileContents.parseFile.test.js index f029b5cae..2cb34f778 100644 --- a/packages/lu/test/parser/lufile/parseFileContents.parseFile.test.js +++ b/packages/lu/test/parser/lufile/parseFileContents.parseFile.test.js @@ -1025,7 +1025,7 @@ describe('parseFile correctly parses utterances', function () { .then(res => { assert.equal(res.LUISJsonStructure.patternAnyEntities.length, 0); assert.equal(res.LUISJsonStructure.entities.length, 0); - assert.equal(res.LUISJsonStructure.utterances[0].text, 'this is a \\{test\\}'); + assert.equal(res.LUISJsonStructure.utterances[0].text, 'this is a {test}'); assert.equal(res.LUISJsonStructure.utterances[1].text, 'this ia a test \\n'); done(); }) @@ -1112,4 +1112,39 @@ describe('parseFile correctly parses utterances', function () { }) .catch(err => done(err)) }) + + it("Correctly parses utterance with escape char \\ to escape entity definition", function (done) { + let testLU = ` + # test + - this is another \\{@from = one} from \\{@to = tokyo} \\in japan`; + parseFile + .parseFile(testLU) + .then((res) => { + assert.equal( + res.LUISJsonStructure.utterances[0].text, + "this is another {@from = one} from {@to = tokyo} \\in japan" + ); + done(); + }) + .catch((err) => done(err)); + }); + + it("Correctly parses utterance that keeps @ at the the beginning of entity name", function (done) { + let testLU = ` + # test + - this is another \\\\{@@from = one} from {@@to = tokyo}`; + parseFile + .parseFile(testLU) + .then((res) => { + assert.equal( + res.LUISJsonStructure.utterances[0].text, + "this is another \\one from tokyo" + ); + assert.equal(res.LUISJsonStructure.entities.length, 2); + assert.equal(res.LUISJsonStructure.entities[0].name, "@from"); + assert.equal(res.LUISJsonStructure.entities[1].name, "@to"); + done(); + }) + .catch((err) => done(err)); + }); })