speech_rule.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.OutputError = exports.Precondition = exports.Action = exports.Component = exports.ActionType = exports.SpeechRule = void 0;
  4. const engine_js_1 = require("../common/engine.js");
  5. const Grammar = require("./grammar.js");
  6. class SpeechRule {
  7. constructor(name, dynamicCstr, precondition, action) {
  8. this.name = name;
  9. this.dynamicCstr = dynamicCstr;
  10. this.precondition = precondition;
  11. this.action = action;
  12. this.context = null;
  13. }
  14. toString() {
  15. return (this.name +
  16. ' | ' +
  17. this.dynamicCstr.toString() +
  18. ' | ' +
  19. this.precondition.toString() +
  20. ' ==> ' +
  21. this.action.toString());
  22. }
  23. }
  24. exports.SpeechRule = SpeechRule;
  25. var ActionType;
  26. (function (ActionType) {
  27. ActionType["NODE"] = "NODE";
  28. ActionType["MULTI"] = "MULTI";
  29. ActionType["TEXT"] = "TEXT";
  30. ActionType["PERSONALITY"] = "PERSONALITY";
  31. })(ActionType || (exports.ActionType = ActionType = {}));
  32. function actionFromString(str) {
  33. switch (str) {
  34. case '[n]':
  35. return ActionType.NODE;
  36. case '[m]':
  37. return ActionType.MULTI;
  38. case '[t]':
  39. return ActionType.TEXT;
  40. case '[p]':
  41. return ActionType.PERSONALITY;
  42. default:
  43. throw 'Parse error: ' + str;
  44. }
  45. }
  46. function actionToString(speechType) {
  47. switch (speechType) {
  48. case ActionType.NODE:
  49. return '[n]';
  50. case ActionType.MULTI:
  51. return '[m]';
  52. case ActionType.TEXT:
  53. return '[t]';
  54. case ActionType.PERSONALITY:
  55. return '[p]';
  56. default:
  57. throw 'Unknown type error: ' + speechType;
  58. }
  59. }
  60. class Component {
  61. static grammarFromString(grammar) {
  62. return Grammar.Grammar.parseInput(grammar);
  63. }
  64. static fromString(input) {
  65. const output = {
  66. type: actionFromString(input.substring(0, 3))
  67. };
  68. let rest = input.slice(3).trim();
  69. if (!rest) {
  70. throw new OutputError('Missing content.');
  71. }
  72. switch (output.type) {
  73. case ActionType.TEXT:
  74. if (rest[0] === '"') {
  75. const quotedString = splitString(rest, '\\(')[0].trim();
  76. if (quotedString.slice(-1) !== '"') {
  77. throw new OutputError('Invalid string syntax.');
  78. }
  79. output.content = quotedString;
  80. rest = rest.slice(quotedString.length).trim();
  81. if (rest.indexOf('(') === -1) {
  82. rest = '';
  83. }
  84. break;
  85. }
  86. case ActionType.NODE:
  87. case ActionType.MULTI:
  88. {
  89. const bracket = rest.indexOf(' (');
  90. if (bracket === -1) {
  91. output.content = rest.trim();
  92. rest = '';
  93. break;
  94. }
  95. output.content = rest.substring(0, bracket).trim();
  96. rest = rest.slice(bracket).trim();
  97. }
  98. break;
  99. }
  100. if (rest) {
  101. const attributes = Component.attributesFromString(rest);
  102. if (attributes.grammar) {
  103. output.grammar = attributes.grammar;
  104. delete attributes.grammar;
  105. }
  106. if (Object.keys(attributes).length) {
  107. output.attributes = attributes;
  108. }
  109. }
  110. return new Component(output);
  111. }
  112. static attributesFromString(attrs) {
  113. if (attrs[0] !== '(' || attrs.slice(-1) !== ')') {
  114. throw new OutputError('Invalid attribute expression: ' + attrs);
  115. }
  116. const attributes = {};
  117. const attribs = splitString(attrs.slice(1, -1), ',');
  118. for (const attr of attribs) {
  119. const colon = attr.indexOf(':');
  120. if (colon === -1) {
  121. attributes[attr.trim()] = 'true';
  122. }
  123. else {
  124. const key = attr.substring(0, colon).trim();
  125. const value = attr.slice(colon + 1).trim();
  126. attributes[key] =
  127. key === Grammar.ATTRIBUTE
  128. ? Component.grammarFromString(value)
  129. : value;
  130. }
  131. }
  132. return attributes;
  133. }
  134. constructor({ type, content, attributes, grammar }) {
  135. this.type = type;
  136. this.content = content;
  137. this.attributes = attributes;
  138. this.grammar = grammar;
  139. }
  140. toString() {
  141. let strs = '';
  142. strs += actionToString(this.type);
  143. strs += this.content ? ' ' + this.content : '';
  144. const attrs = this.attributesToString();
  145. strs += attrs ? ' ' + attrs : '';
  146. return strs;
  147. }
  148. grammarToString() {
  149. return this.getGrammar().join(':');
  150. }
  151. getGrammar() {
  152. if (!this.grammar) {
  153. return [];
  154. }
  155. const attribs = [];
  156. for (const [key, val] of Object.entries(this.grammar)) {
  157. attribs.push(val === true ? key : val === false ? `!${key}` : `${key}=${val}`);
  158. }
  159. return attribs;
  160. }
  161. attributesToString() {
  162. const attribs = this.getAttributes();
  163. const grammar = this.grammarToString();
  164. if (grammar) {
  165. attribs.push('grammar:' + grammar);
  166. }
  167. return attribs.length > 0 ? '(' + attribs.join(', ') + ')' : '';
  168. }
  169. getAttributes() {
  170. if (!this.attributes) {
  171. return [];
  172. }
  173. const attribs = [];
  174. for (const [key, val] of Object.entries(this.attributes)) {
  175. attribs.push(val === 'true' ? key : `${key}:${val}`);
  176. }
  177. return attribs;
  178. }
  179. }
  180. exports.Component = Component;
  181. class Action {
  182. static fromString(input) {
  183. const comps = splitString(input, ';')
  184. .filter(function (x) {
  185. return x.match(/\S/);
  186. })
  187. .map(function (x) {
  188. return x.trim();
  189. });
  190. const newComps = [];
  191. for (let i = 0, m = comps.length; i < m; i++) {
  192. const comp = Component.fromString(comps[i]);
  193. if (comp) {
  194. newComps.push(comp);
  195. }
  196. }
  197. Action.naiveSpan(newComps);
  198. return new Action(newComps);
  199. }
  200. static naiveSpan(comps) {
  201. var _a;
  202. let first = false;
  203. for (let i = 0, comp; (comp = comps[i]); i++) {
  204. if (first &&
  205. (comp.type !== ActionType.TEXT ||
  206. (comp.content[0] !== '"' && !comp.content.match(/^CSF/))))
  207. continue;
  208. if (!first && comp.type === ActionType.PERSONALITY)
  209. continue;
  210. if (!first) {
  211. first = true;
  212. continue;
  213. }
  214. if ((_a = comp.attributes) === null || _a === void 0 ? void 0 : _a.span)
  215. continue;
  216. const next = comps[i + 1];
  217. if (next && next.type !== ActionType.NODE)
  218. continue;
  219. Action.addNaiveSpan(comp, next ? next.content : 'LAST');
  220. }
  221. }
  222. static addNaiveSpan(comp, span) {
  223. if (!comp.attributes) {
  224. comp.attributes = {};
  225. }
  226. comp.attributes['span'] = span;
  227. }
  228. constructor(components) {
  229. this.components = components;
  230. }
  231. toString() {
  232. const comps = this.components.map(function (c) {
  233. return c.toString();
  234. });
  235. return comps.join('; ');
  236. }
  237. }
  238. exports.Action = Action;
  239. class Precondition {
  240. static constraintValue(constr, priorities) {
  241. for (let i = 0, regexp; (regexp = priorities[i]); i++) {
  242. if (constr.match(regexp)) {
  243. return ++i;
  244. }
  245. }
  246. return 0;
  247. }
  248. toString() {
  249. const constrs = this.constraints.join(', ');
  250. return `${this.query}, ${constrs} (${this.priority}, ${this.rank})`;
  251. }
  252. constructor(query, ...cstr) {
  253. this.query = query;
  254. this.constraints = cstr;
  255. const [exists, user] = this.presetPriority();
  256. this.priority = exists ? user : this.calculatePriority();
  257. }
  258. calculatePriority() {
  259. const query = Precondition.constraintValue(this.query, Precondition.queryPriorities);
  260. if (!query) {
  261. return 0;
  262. }
  263. const match = this.query.match(/^self::.+\[(.+)\]/);
  264. let attr = 0;
  265. if ((match === null || match === void 0 ? void 0 : match.length) && match[1]) {
  266. const inner = match[1];
  267. attr = Precondition.constraintValue(inner, Precondition.attributePriorities);
  268. }
  269. return query * 100 + attr * 10;
  270. }
  271. presetPriority() {
  272. if (!this.constraints.length) {
  273. return [false, 0];
  274. }
  275. const last = this.constraints[this.constraints.length - 1].match(/^priority=(.*$)/);
  276. if (!last) {
  277. return [false, 0];
  278. }
  279. this.constraints.pop();
  280. const numb = parseFloat(last[1]);
  281. return [true, isNaN(numb) ? 0 : numb];
  282. }
  283. }
  284. exports.Precondition = Precondition;
  285. Precondition.queryPriorities = [
  286. /^self::\*$/,
  287. /^self::[\w-]+$/,
  288. /^self::\*\[.+\]$/,
  289. /^self::[\w-]+\[.+\]$/
  290. ];
  291. Precondition.attributePriorities = [
  292. /^@[\w-]+$/,
  293. /^@[\w-]+!=".+"$/,
  294. /^not\(contains\(@[\w-]+,\s*".+"\)\)$/,
  295. /^contains\(@[\w-]+,".+"\)$/,
  296. /^@[\w-]+=".+"$/
  297. ];
  298. class OutputError extends engine_js_1.SREError {
  299. constructor(msg) {
  300. super(msg);
  301. this.name = 'RuleError';
  302. }
  303. }
  304. exports.OutputError = OutputError;
  305. function splitString(str, sep) {
  306. const strList = [];
  307. let prefix = '';
  308. while (str !== '') {
  309. const sepPos = str.search(sep);
  310. if (sepPos === -1) {
  311. if ((str.match(/"/g) || []).length % 2 !== 0) {
  312. throw new OutputError('Invalid string in expression: ' + str);
  313. }
  314. strList.push(prefix + str);
  315. prefix = '';
  316. str = '';
  317. }
  318. else if ((str.substring(0, sepPos).match(/"/g) || []).length % 2 === 0) {
  319. strList.push(prefix + str.substring(0, sepPos));
  320. prefix = '';
  321. str = str.substring(sepPos + 1);
  322. }
  323. else {
  324. const nextQuot = str.substring(sepPos).search('"');
  325. if (nextQuot === -1) {
  326. throw new OutputError('Invalid string in expression: ' + str);
  327. }
  328. else {
  329. prefix = prefix + str.substring(0, sepPos + nextQuot + 1);
  330. str = str.substring(sepPos + nextQuot + 1);
  331. }
  332. }
  333. }
  334. if (prefix) {
  335. strList.push(prefix);
  336. }
  337. return strList;
  338. }