/// <reference types="node" />
import * as events from 'events';
import { Choice, Derivation, NonTerminal } from './runtime';
import { SemanticAction, KeyFunction, RuleAttributes, ContextPhrase, ContextTable, ContextFunction, GrammarOptions } from './types';
declare type RuleExpansionChunk = string | Choice | NonTerminal;
interface FunctionTable<StateType> {
    answer?: (state: StateType, value: unknown, contextTable: ContextTable) => StateType | null;
    context?: ContextFunction<StateType>;
    [key: string]: ((...args: any[]) => any) | undefined;
}
declare type ContextInitializer<ContextType, StateType> = (previousTurn: ContextType, functionTable: FunctionTable<StateType>, contextTable: ContextTable) => ContextPhrase[] | null;
interface GenericSentenceGeneratorOptions extends GrammarOptions {
    locale: string;
    templateFiles: string[];
    rootSymbol?: string;
    targetPruningSize: number;
    maxDepth: number;
    maxConstants: number;
    rng: () => number;
}
interface BasicSentenceGeneratorOptions {
    contextual: false;
    contextInitializer?: undefined;
}
interface ContextualSentenceGeneratorOptions<ContextType, StateType> {
    contextual: true;
    rootSymbol?: string;
    contextInitializer: ContextInitializer<ContextType, StateType>;
}
export declare type SentenceGeneratorOptions<ContextType, RootOutputType> = GenericSentenceGeneratorOptions & (BasicSentenceGeneratorOptions | ContextualSentenceGeneratorOptions<ContextType, RootOutputType>);
interface Constant {
    token: string;
    value: unknown;
}
/**
 * Low-level class that generates sentences and associated logical forms,
 * given a grammar expressed as Genie template files.
 */
export default class SentenceGenerator<ContextType, StateType, RootOutputType = StateType> extends events.EventEmitter {
    private _templateFiles;
    private _langPack;
    private _entityAllocator;
    private _options;
    private _contextual;
    private _nonTermTable;
    private _nonTermList;
    private _rules;
    private _contextTable;
    private _functionTable;
    private _rootSymbol;
    private _rootIndex;
    private _contextInitializer;
    private _constantMap;
    private _finalized;
    private _averagePruningFactor;
    private _minDistanceFromRoot;
    private _nonTermHasContext;
    private _charts;
    private _progress;
    constructor(options: SentenceGeneratorOptions<ContextType, StateType>);
    initialize(): Promise<void>;
    get progress(): number;
    hasSymbol(symbol: string): boolean;
    hasContext(symbol: string): boolean;
    get contextTable(): ContextTable;
    private _internalDeclareSymbol;
    declareFunction(name: string, fn: (...args: any[]) => any): void;
    declareContext(context: string): void;
    declareSymbol(symbol: string): void;
    private _lookupNonTerminal;
    private _addRuleInternal;
    addConstants(symbol: string, token: string, type: any, keyFunction: KeyFunction<any>, attributes?: RuleAttributes): void;
    addRule<ArgTypes extends unknown[], ResultType>(symbol: string, expansion: RuleExpansionChunk[], semanticAction: SemanticAction<ArgTypes, ResultType>, keyFunction: KeyFunction<ResultType> | undefined, attributes?: RuleAttributes): void;
    private _typecheck;
    private _computeHasContext;
    private _computeDistanceFromRoot;
    private _addAutomaticRepeat;
    private _optimizeConstLikeNonTerminals;
    finalize(): void;
    private _estimateDepthSize;
    private _enableAllRules;
    private _disableUnreachableRules;
    invokeFunction<K extends keyof FunctionTable<StateType>>(name: K, ...args: Parameters<NonNullable<FunctionTable<StateType>[K]>>): ReturnType<NonNullable<FunctionTable<StateType>[K]>>;
    addConstantsFromContext(constants: {
        [key: string]: Constant[];
    }): void;
    private _removeTemporaryRules;
    private _disableRulesForConstants;
    /**
     * Generate a single sentence or dialogue turn, given the single context.
     *
     * This method will expand the grammar then sample exactly one derivation out of the root 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 {any} - the current context
     * @return {Derivation} - the sampled derivation
     */
    generateOne(context: ContextType): Derivation<RootOutputType> | 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;
    /**
     * Generate a batch of sentences (or dialogue turns), given the batch of contexts.
     *
     * This method is optimized for batch generation, and will cache intermediate generations
     * that do not depend on the context between subsequent calls.
     */
    generate(contextInputs: readonly ContextType[], callback: (depth: number, derivation: Derivation<RootOutputType>) => void): void;
}
export {};
