///
import * as events from 'events';
import * as I18n from '../i18n';
import { Replaceable, ReplacedResult } from '../utils/template-string';
import { Derivation, NonTerminal } from './runtime';
import { SemanticAction, KeyFunction, RuleAttributes, ContextPhrase, ContextTable, GrammarOptions } from './types';
import ThingpediaLoader from '../templates/load-thingpedia';
interface GenericSentenceGeneratorOptions extends GrammarOptions {
locale: string;
templateFiles?: string[];
rootSymbol?: string;
targetPruningSize: number;
maxDepth: number;
maxConstants: number;
rng: () => number;
logPrefix?: string;
}
interface BasicSentenceGeneratorOptions {
contextual: false;
}
interface ContextualSentenceGeneratorOptions {
contextual: true;
rootSymbol?: string;
}
export declare type SentenceGeneratorOptions = GenericSentenceGeneratorOptions & (BasicSentenceGeneratorOptions | ContextualSentenceGeneratorOptions);
interface Constant {
token: ReplacedResult;
value: unknown;
}
/**
* Low-level class that generates sentences and associated logical forms,
* given a grammar expressed as Genie template files.
*/
export default class SentenceGenerator extends events.EventEmitter {
private _templateFiles;
private _langPack;
private _entityAllocator;
private _tpLoader;
private _logPrefix;
private _options;
private _contextual;
private _nonTermTable;
private _nonTermList;
private _rules;
private _contextTable;
private _constantMap;
private _finalized;
private _nonTermHasContext;
private _charts;
private _progress;
private _stackDepth;
constructor(options: SentenceGeneratorOptions);
get tpLoader(): ThingpediaLoader;
get langPack(): I18n.LanguagePack;
/**
* Log a debug message.
*
* This is a wrapper over `console.log` that includes a logging prefix
* to disambiguate recursive calls and parallel generation.
*
* @param message the message to log
* @param args additional arguments to `console.log`
*/
log(message: string, ...args: []): void;
initialize(): Promise;
get progress(): number;
hasSymbol(symbol: string): boolean;
hasContext(symbol: string): boolean;
get contextTable(): ContextTable;
private _internalDeclareSymbol;
declareContext(context: string): void;
declareSymbol(symbol: string): void;
private _lookupNonTerminal;
private _addRuleInternal;
addConstants(symbol: string, token: string, type: any, keyFunction: KeyFunction, attributes?: RuleAttributes): void;
addRule(symbol: string, expansion: NonTerminal[], sentenceTemplate: string | Replaceable, semanticAction: SemanticAction, keyFunction: KeyFunction | undefined, attributes?: RuleAttributes): void;
private _typecheck;
private _computeHasContext;
private _addAutomaticRepeat;
finalize(): void;
addConstantsFromContext(constants: {
[key: string]: Constant[];
}): void;
private _enableAllRules;
private _removeTemporaryRules;
private _disableRulesForConstants;
/**
* Generate a single derivation for a particular symbol in the grammar, given the single context.
*
* This method will expand the grammar then sample exactly one derivation out of the given non-terminal.
*
* This method is optimized for individual generation, and prune the set of enabled rules
* based on the context. It cannot be called for non-contextual grammars. No `progress` events will
* be emitted during this method.
*
* @param context - the current context
* @param nonTerm - the symbol to generate
* @return {Derivation} - the sampled derivation
*/
generateOne(contexts: Iterable, nonTerm: string): Derivation | undefined;
private _getRuleTarget;
/**
* Convert the context inputs into something suitable to pass to the semantic functions.
*
* `contextInputs` is an array of arbitrary objects, each corresponding to one possible
* context to use. Each object will be passed to the `contextInitializer` function that
* was passed when constructing the grammar.
*
* The contextInitializer returns a tuple with the "context tags" (a list of grammar
* non-terminals declared in a "context" statement) and the "context info", which is actually
* passed to the semantic function.
* The input to the context initializer and the info are stored in a Context object,
* which is then set as the .context property of the derivation.
*
* When generating agent sentences, contextInputs is an array of PartialDialogues,
* each having .context which is the C: state of the dialogue.
* We call the "context" function to compute the tags and the info.
*
* When generating user sentences, contextInputs is an array of agent turns. The turns
* already contain the tags and the context info (computed by the semantic function
* of the agent derivation).
*
* This fairly convoluted design allows two things:
* - "Grammar" (this class) has no notion of user or agent, all it knows is to put the right
* stuff in the right non-terminals and generate.
* - The templates can define arbitrary tags for the context, and can define arbitrary functions
* to tag the C: state context (the result of simulation).
* - The templates can pass arbitrary information from the agent turns to the user turns,
* including information that is not representable in a ThingTalk dialogue state.
*/
private _initializeContexts;
/**
* Reset this generator, and prepare for the next turn of generation.
*
* This will clear all intermediate derivations that depend on the current set of contexts.
*
* If hard is true, it will also clear all other derivations and reset the chart table.
* Otheriwse, it will not clear other intermediate derivations.
*
* @param hard - whether to reset all derivations or only those that depend on the context
*/
reset(hard?: boolean): void;
private _initializeCharts;
/**
* Ensure that the rule is ready to generate at the given depth.
*
* This will ensure that all non-terminals referenced by the rule have been generated
* at lower depths.
*
* @param rule
* @param atDepth the depth at which rule will be expanded
* @returns whether the rule should be expanded at all
*/
private _ensureRuleReadyToGenerate;
/**
* Ensure that the given non-terminal is fully generated at the given depth.
*
* This will recursively generate the non-terminals that feed into the given one
* at lower depths, then apply all the rules for this non-terminal.
*
* This method has no effect if the non-terminal was already generated at the given
* depth since the last call to {@link reset}. It also has no effect if depth is
* negative.
*
* @param nonTermIndex the index of the non-terminal to generate
* @param depth the depth at which to generate
* @param mode whether to generate and sample randomly, or whether to choose only
* the derivations with the highest priority
* @returns the size of the non terminal at this depth
*/
private _ensureGenerated;
private _getAllDerivations;
/**
* Generate a batch of derivations for the given symbol, given the batch of contexts.
*
*/
generate(contextPhrases: Iterable, symbol: string): Iterable>;
}
export {};