Created
November 27, 2019 16:07
-
-
Save marcmartino/3040c96bcf1f16cf33865b34365ededd to your computer and use it in GitHub Desktop.
first attempt at fleshing out cogeneration of regex and grammars based on the same adts for use in speech recognition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum QtyOperators { | |
Optional, | |
OnePlus, | |
ZeroPlus | |
} | |
type SpeechExpectation = { | |
captureName?: string; | |
qty?: QtyOperators; | |
inputs: (SpeechExpectation | string)[]; | |
union?: true; | |
}; | |
// interface CaptureAugmentedRegexp<T extends string> extends RegExpMatchArray { | |
// // thinking that T can be a string literal and then it can be explicity | |
// // noted in the groups?: {} record | |
// } | |
const genRegex = (expectation: SpeechExpectation): RegExp => { | |
return RegExp(genRegexSubstring(expectation), "mi"); | |
}; | |
const genRegexUnionStr = ({ inputs, union }: SpeechExpectation): string => | |
inputs | |
.map(input => | |
typeof input === "string" ? input : genRegexSubstring(input) | |
) | |
.join(union ? "|" : " "); | |
const genRegexSubstring = (expec: SpeechExpectation): string => | |
"(" + | |
genCaptureGroupName(expec.captureName) + | |
genRegexUnionStr(expec) + | |
")" + | |
genRegexQtyStr(expec.qty); | |
const genCaptureGroupName = (groupName: string | undefined) => | |
groupName ? `?<${groupName}>` : "?:"; | |
const genRegexQtyStr = (qty: QtyOperators | undefined) => { | |
if (typeof qty === "undefined") return ""; | |
switch (qty) { | |
case QtyOperators.Optional: | |
return "?"; | |
case QtyOperators.OnePlus: | |
return "+"; | |
case QtyOperators.ZeroPlus: | |
return "*"; | |
default: | |
return ""; | |
// return assertNever(qty); | |
} | |
}; | |
interface JSGFConfig { | |
packageName?: string[]; | |
// ruleName?: string; | |
charEncoding?: string; | |
locale?: string; | |
} | |
type JSGFText = string; | |
const genJSGFQtyStr = (qty: QtyOperators | undefined) => { | |
if (typeof qty === "undefined") return ""; | |
switch (qty) { | |
case QtyOperators.Optional: | |
return ""; | |
case QtyOperators.OnePlus: | |
return "+"; | |
case QtyOperators.ZeroPlus: | |
return "*"; | |
default: | |
return ""; | |
//return assertNever(qty) | |
} | |
}; | |
const genJSGFSubCommand = ({ inputs, qty, union }: SpeechExpectation) => { | |
const subcommandString = inputs | |
.map((input: SpeechExpectation | string): string => | |
typeof input === "string" ? input : genJSGFSubCommand(input) | |
) | |
.join(union ? "|" : " "); | |
return ( | |
(qty === QtyOperators.Optional ? ["[", "]"] : ["(", ")"]).join( | |
subcommandString | |
) + genJSGFQtyStr(qty) | |
); | |
}; | |
const genJSGFCommand = (ex: SpeechExpectation) => | |
`public <autoGeneratedCommand> = ${genJSGFSubCommand(ex)}`; | |
const genJSGF = (ex: SpeechExpectation, config: JSGFConfig = {}) => { | |
return `#JSGF V1.0; ${config.charEncoding ? config.charEncoding : ""} ${ | |
config.locale ? config : "" | |
}; | |
grammar speechStreams.commands.autogen; | |
${genJSGFCommand(ex)} | |
`; | |
}; | |
const greeting: SpeechExpectation = { | |
inputs: ["hello", "hey", "howdy", "hi"], | |
union: true | |
}; | |
const names: SpeechExpectation = { | |
inputs: ["german", "germi", "germanchu"], | |
captureName: "name", | |
union: true | |
}; | |
const endingPhrase: SpeechExpectation = { | |
inputs: ["my friend", "bro"], | |
qty: QtyOperators.Optional, | |
union: true | |
}; | |
const germanGreeting: SpeechExpectation = { | |
inputs: [greeting, names, endingPhrase] | |
}; | |
const compileExpectation = (ex: SpeechExpectation) => { | |
const grammar = new SpeechGrammar(); | |
grammar.src = genJSGF(ex); | |
return { | |
regex: genRegex(ex), | |
grammar | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment