speech_rule_context.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { Span } from '../audio/span.js';
  2. import * as XpathUtil from '../common/xpath_util.js';
  3. import * as srf from './speech_rule_functions.js';
  4. export class SpeechRuleContext {
  5. constructor() {
  6. this.customQueries = new srf.CustomQueries();
  7. this.customStrings = new srf.CustomStrings();
  8. this.contextFunctions = new srf.ContextFunctions();
  9. this.customGenerators = new srf.CustomGenerators();
  10. }
  11. applyCustomQuery(node, funcName) {
  12. const func = this.customQueries.lookup(funcName);
  13. return func ? func(node) : null;
  14. }
  15. applySelector(node, expr) {
  16. const result = this.applyCustomQuery(node, expr);
  17. return result || XpathUtil.evalXPath(expr, node);
  18. }
  19. applyQuery(node, expr) {
  20. const results = this.applySelector(node, expr);
  21. if (results.length > 0) {
  22. return results[0];
  23. }
  24. return null;
  25. }
  26. applyConstraint(node, expr) {
  27. const result = this.applyQuery(node, expr);
  28. return !!result || XpathUtil.evaluateBoolean(expr, node);
  29. }
  30. constructString(node, expr) {
  31. const result = this.constructString_(node, expr);
  32. return Array.isArray(result)
  33. ? result.map((x) => x.speech).join('')
  34. : result;
  35. }
  36. constructSpan(node, expr, def) {
  37. const result = this.constructString_(node, expr);
  38. if (Array.isArray(result)) {
  39. const last = result[result.length - 1];
  40. last.attributes = Object.assign({}, def, last.attributes);
  41. return result;
  42. }
  43. else {
  44. return [Span.node(result, node, def)];
  45. }
  46. }
  47. constructString_(node, expr) {
  48. if (!expr) {
  49. return '';
  50. }
  51. if (expr.charAt(0) === '"') {
  52. return expr.slice(1, -1);
  53. }
  54. const func = this.customStrings.lookup(expr);
  55. if (func) {
  56. return func(node);
  57. }
  58. return XpathUtil.evaluateString(expr, node);
  59. }
  60. parse(functions) {
  61. const functs = Array.isArray(functions)
  62. ? functions
  63. : Object.entries(functions);
  64. for (const func of functs) {
  65. const kind = func[0].slice(0, 3);
  66. switch (kind) {
  67. case 'CQF':
  68. this.customQueries.add(func[0], func[1]);
  69. break;
  70. case 'CSF':
  71. this.customStrings.add(func[0], func[1]);
  72. break;
  73. case 'CTF':
  74. this.contextFunctions.add(func[0], func[1]);
  75. break;
  76. case 'CGF':
  77. this.customGenerators.add(func[0], func[1]);
  78. break;
  79. default:
  80. console.error('FunctionError: Invalid function name ' + func[0]);
  81. }
  82. }
  83. }
  84. }