UNPKG

speech-rule-engine

Version:

A standalone speech rule engine for XML structures, based on the original engine from ChromeVox.

278 lines (277 loc) 12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClearspeakPreferences = void 0; const engine_js_1 = require("../common/engine.js"); const dynamic_cstr_js_1 = require("../rule_engine/dynamic_cstr.js"); const dynamic_cstr_js_2 = require("../rule_engine/dynamic_cstr.js"); const MathCompoundStore = require("../rule_engine/math_compound_store.js"); const speech_rule_engine_js_1 = require("../rule_engine/speech_rule_engine.js"); const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js"); const clearspeak_preference_string_js_1 = require("./clearspeak_preference_string.js"); class ClearspeakPreferences extends dynamic_cstr_js_1.DynamicCstr { static comparator() { return new Comparator(engine_js_1.Engine.getInstance().dynamicCstr, dynamic_cstr_js_2.DynamicProperties.createProp([dynamic_cstr_js_1.DynamicCstr.DEFAULT_VALUES[dynamic_cstr_js_2.Axis.LOCALE]], [dynamic_cstr_js_1.DynamicCstr.DEFAULT_VALUES[dynamic_cstr_js_2.Axis.MODALITY]], [dynamic_cstr_js_1.DynamicCstr.DEFAULT_VALUES[dynamic_cstr_js_2.Axis.DOMAIN]], [dynamic_cstr_js_1.DynamicCstr.DEFAULT_VALUES[dynamic_cstr_js_2.Axis.STYLE]])); } static getLocalePreferences(opt_dynamic) { const dynamic = opt_dynamic || MathCompoundStore.enumerate(speech_rule_engine_js_1.SpeechRuleEngine.getInstance().enumerate()); return ClearspeakPreferences.getLocalePreferences_(dynamic); } static relevantPreferences(node) { const roles = SEMANTIC_MAPPING_[node.type]; if (!roles) { return 'ImpliedTimes'; } const cons = roles[node.role] || roles['']; if (!cons) { return 'ImpliedTimes'; } if (typeof cons === 'string') { return cons; } else { return testSpecial(cons, node) || 'ImpliedTimes'; } } static getLocalePreferences_(dynamic) { const result = {}; for (const locale of Object.keys(dynamic)) { if (!dynamic[locale]['speech'] || !dynamic[locale]['speech']['clearspeak']) { continue; } const locPrefs = Object.keys(dynamic[locale]['speech']['clearspeak']); if (locPrefs.length < 3) continue; const prefs = (result[locale] = {}); for (const axis in clearspeak_preference_string_js_1.PREFERENCES.getProperties()) { const allSty = clearspeak_preference_string_js_1.PREFERENCES.getProperties()[axis]; const values = [axis + '_Auto']; if (allSty) { for (const sty of allSty) { if (locPrefs.indexOf(axis + '_' + sty) !== -1) { values.push(axis + '_' + sty); } } } prefs[axis] = values; } } return result; } constructor(cstr, preference) { super(cstr); this.preference = preference; } equal(cstr) { const top = super.equal(cstr); if (!top) { return false; } const keys = Object.keys(this.preference); const preference = cstr.preference; if (keys.length !== Object.keys(preference).length) { return false; } for (let i = 0, key; (key = keys[i]); i++) { if (this.preference[key] !== preference[key]) { return false; } } return true; } } exports.ClearspeakPreferences = ClearspeakPreferences; class Comparator extends dynamic_cstr_js_2.DefaultComparator { constructor(cstr, props) { super(cstr, props); this.preference = cstr instanceof ClearspeakPreferences ? cstr.preference : {}; } match(cstr) { if (!(cstr instanceof ClearspeakPreferences)) { return super.match(cstr); } if (cstr.getComponents()[dynamic_cstr_js_2.Axis.STYLE] === 'default') { return true; } const keys = Object.keys(cstr.preference); for (let i = 0, key; (key = keys[i]); i++) { if (this.preference[key] !== cstr.preference[key]) { return false; } } return true; } compare(cstr1, cstr2) { const top = super.compare(cstr1, cstr2); if (top !== 0) { return top; } const pref1 = cstr1 instanceof ClearspeakPreferences; const pref2 = cstr2 instanceof ClearspeakPreferences; if (!pref1 && pref2) { return 1; } if (pref1 && !pref2) { return -1; } if (!pref1 && !pref2) { return 0; } const length1 = Object.keys(cstr1.preference).length; const length2 = Object.keys(cstr2.preference).length; return length1 > length2 ? -1 : length1 < length2 ? 1 : 0; } } class Parser extends dynamic_cstr_js_2.DynamicCstrParser { constructor() { super([dynamic_cstr_js_2.Axis.LOCALE, dynamic_cstr_js_2.Axis.MODALITY, dynamic_cstr_js_2.Axis.DOMAIN, dynamic_cstr_js_2.Axis.STYLE]); } parse(str) { const initial = super.parse(str); let style = initial.getValue(dynamic_cstr_js_2.Axis.STYLE); const locale = initial.getValue(dynamic_cstr_js_2.Axis.LOCALE); const modality = initial.getValue(dynamic_cstr_js_2.Axis.MODALITY); let pref = {}; if (style !== dynamic_cstr_js_1.DynamicCstr.DEFAULT_VALUE) { pref = this.fromPreference(style); style = this.toPreference(pref); } return new ClearspeakPreferences({ locale: locale, modality: modality, domain: 'clearspeak', style: style }, pref); } fromPreference(pref) { return (0, clearspeak_preference_string_js_1.fromPreference)(pref); } toPreference(pref) { return (0, clearspeak_preference_string_js_1.toPreference)(pref); } } const REVERSE_MAPPING = [ ['AbsoluteValue', semantic_meaning_js_1.SemanticType.FENCED, semantic_meaning_js_1.SemanticRole.NEUTRAL], ['AbsoluteValue', semantic_meaning_js_1.SemanticType.FENCED, semantic_meaning_js_1.SemanticRole.METRIC], ['Bar', semantic_meaning_js_1.SemanticType.OVERSCORE, ''], ['Caps', semantic_meaning_js_1.SemanticType.IDENTIFIER, semantic_meaning_js_1.SemanticRole.LATINLETTER, 'category:Lu'], ['CombinationPermutation', semantic_meaning_js_1.SemanticType.APPL, semantic_meaning_js_1.SemanticRole.UNKNOWN], ['Currency', semantic_meaning_js_1.SemanticType.IDENTIFIER, semantic_meaning_js_1.SemanticRole.UNIT, 'unit:currency'], ['Currency', semantic_meaning_js_1.SemanticType.INFIXOP, semantic_meaning_js_1.SemanticRole.UNIT, 'unit:currency'], ['Enclosed', semantic_meaning_js_1.SemanticType.ENCLOSE, ''], ['Ellipses', semantic_meaning_js_1.SemanticType.PUNCTUATION, semantic_meaning_js_1.SemanticRole.ELLIPSIS], ['Exponent', semantic_meaning_js_1.SemanticType.SUPERSCRIPT, ''], ['Fraction', semantic_meaning_js_1.SemanticType.FRACTION, ''], ['Functions', semantic_meaning_js_1.SemanticType.APPL, semantic_meaning_js_1.SemanticRole.SIMPLEFUNC], ['ImpliedTimes', semantic_meaning_js_1.SemanticType.OPERATOR, semantic_meaning_js_1.SemanticRole.IMPLICIT], ['Log', semantic_meaning_js_1.SemanticType.APPL, semantic_meaning_js_1.SemanticRole.PREFIXFUNC, 'appl:Logarithm'], ['Log', semantic_meaning_js_1.SemanticType.FUNCTION, semantic_meaning_js_1.SemanticRole.PREFIXFUNC, 'category:Logarithm'], ['Matrix', semantic_meaning_js_1.SemanticType.MATRIX, ''], ['Matrix', semantic_meaning_js_1.SemanticType.VECTOR, ''], ['MultiLineLabel', semantic_meaning_js_1.SemanticType.MULTILINE, semantic_meaning_js_1.SemanticRole.LABEL], ['MultiLinePausesBetweenColumns', semantic_meaning_js_1.SemanticType.MULTILINE, semantic_meaning_js_1.SemanticRole.TABLE], ['MultiLineOverview', semantic_meaning_js_1.SemanticType.MULTILINE, ''], ['MultiLineLabel', semantic_meaning_js_1.SemanticType.TABLE, semantic_meaning_js_1.SemanticRole.LABEL], ['MultiLinePausesBetweenColumns', semantic_meaning_js_1.SemanticType.TABLE, ''], ['MultiLineOverview', semantic_meaning_js_1.SemanticType.TABLE, ''], ['MultiLineLabel', semantic_meaning_js_1.SemanticType.CASES, semantic_meaning_js_1.SemanticRole.LABEL], ['MultiLinePausesBetweenColumns', semantic_meaning_js_1.SemanticType.CASES, ''], ['MultiLineOverview', semantic_meaning_js_1.SemanticType.CASES, ''], [ 'MultsymbolDot', semantic_meaning_js_1.SemanticType.OPERATOR, semantic_meaning_js_1.SemanticRole.MULTIPLICATION, 'content:22C5' ], [ 'MultsymbolX', semantic_meaning_js_1.SemanticType.OPERATOR, semantic_meaning_js_1.SemanticRole.MULTIPLICATION, 'content:00D7' ], ['Paren', semantic_meaning_js_1.SemanticType.FENCED, semantic_meaning_js_1.SemanticRole.LEFTRIGHT], ['Prime', semantic_meaning_js_1.SemanticType.PUNCTUATION, semantic_meaning_js_1.SemanticRole.PRIME], ['Roots', semantic_meaning_js_1.SemanticType.ROOT, ''], ['Roots', semantic_meaning_js_1.SemanticType.SQRT, ''], ['SetMemberSymbol', semantic_meaning_js_1.SemanticType.OPERATOR, semantic_meaning_js_1.SemanticRole.ELEMENT], ['Sets', semantic_meaning_js_1.SemanticType.FENCED, semantic_meaning_js_1.SemanticRole.SETEXT], [ 'TriangleSymbol', semantic_meaning_js_1.SemanticType.IDENTIFIER, semantic_meaning_js_1.SemanticRole.GREEKLETTER, 'content:0394' ], ['Trig', semantic_meaning_js_1.SemanticType.APPL, semantic_meaning_js_1.SemanticRole.PREFIXFUNC, 'appl:Trigonometric'], [ 'Trig', semantic_meaning_js_1.SemanticType.FUNCTION, semantic_meaning_js_1.SemanticRole.PREFIXFUNC, 'category:Trigonometric' ], ['VerticalLine', semantic_meaning_js_1.SemanticType.PUNCTUATED, semantic_meaning_js_1.SemanticRole.VBAR], ['VerticalLine', semantic_meaning_js_1.SemanticType.PUNCTUATION, semantic_meaning_js_1.SemanticRole.VBAR] ]; const SEMANTIC_MAPPING_ = (function () { const result = {}; for (let i = 0, triple; (triple = REVERSE_MAPPING[i]); i++) { const pref = triple[0]; const special = triple[3]; let role = result[triple[1]]; if (!role) { role = {}; result[triple[1]] = role; } if (!special) { role[triple[2]] = pref; continue; } let specialize = role[triple[2]]; if (!specialize) { specialize = {}; role[triple[2]] = specialize; } specialize[special] = pref; } return result; })(); function testSpecial(special, node) { for (const [pred, res] of Object.entries(special)) { if (executeSpecial(pred, node)) { return res; } } return ''; } function executeSpecial(special, node) { const [pred, arg] = special.split(':'); if (!pred) { return false; } const func = specialPred[pred]; if (!func) { return false; } return func(node, arg); } const specialPred = { category: (node, arg) => { return MathCompoundStore.lookupCategory(node.textContent) === arg; }, content: (node, arg) => { return node.textContent === String.fromCodePoint(parseInt(arg, 16)); }, appl: (node, arg) => { const func = node.childNodes[0]; return func ? MathCompoundStore.lookupCategory(func.textContent) === arg : false; }, unit: (node, arg) => { return MathCompoundStore.lookupCategory(node.textContent + ':unit') === arg; } }; engine_js_1.Engine.getInstance().comparators['clearspeak'] = ClearspeakPreferences.comparator; engine_js_1.Engine.getInstance().parsers['clearspeak'] = new Parser();