import { Context } from './Encoding'; export type Option = string | number | boolean | Record; export interface OptionsStanza { options: { [key: string]: Option; }; context: { [key: string]: Option; }; } export interface OptionsAST { expressions: { [key: string]: Expr[]; }; simpleOptions: { [key: string]: Option; }; context: { [key: string]: Option; }; } /** * Notice that the AST has an identical top-level structure to the Encoding. This is because ALL the AST does * is parse the DSL expressions, and represent them as Field objects. An AST will look like * Example: * { * context:{ * gradientContext:["red", "yellow", "green"] * * }, * * fields:{ * field1:{ * value:[{op:"selectByPosition", args:["FIRST"]},{op:"expects", args:["NUMERIC"]}] * }, * field2:{ * value:[{op:"selectByPosition", args:["SECOND"]},{op:"expects", args:["NUMERIC"]}], * computed:{ * color:[{op:"gradient", args:["gradientContext"]},{op:"toRgb", args:[]}], * smell: [{op:"odor", args:["'delicious"]}] * } * } * * } * * } * * So, ALL that happened is we converted DSL which is pipe-separated method calls into arrays of operations * (ops) and their arguments. Other than that the AST is the same as Encoding. Which of course makes perfect * sense because by definition an AST is simply a way to structure the information in a DSL. */ export interface AST { dimensions: { [key: string]: Dimension; }; context: { [key: string]: Context; }; } export interface DimensionEncoding { value: ExpressionDSL; } export type ExpressionDSL = string; export interface Dimension { value: Expr[]; } export type Expr = Method | ParserSymbol; export interface Method { type: 'method'; name: string; args: ParserSymbol[]; } export interface ParserSymbol { type: 'number' | 'string' | 'identifier'; v: number | string; } export interface LiteralSymbol { type: 'number' | 'string'; v: number | string; } export declare const LITERAL_TYPES: string[];