@andreasnicolaou/typescript-expression-language
Version:
TypeScript implementation of symfony/expression-language
895 lines (870 loc) • 26.5 kB
TypeScript
import { LRUCache } from 'lru-cache';
/**
* Represents a node in an abstract syntax tree (AST) for an expression language.
* @class Node
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class Node {
nodes: Record<string, Node>;
attributes: Record<string, any>;
constructor(nodes?: Record<string, Node>, attributes?: Record<string, any>);
/**
* Converts the Node instance to a string representation.
* @returns The string representation of the Node.
* @memberof Node
*/
toString(): string;
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof Node
*/
compile(compiler: Compiler): void;
/**
* Evaluates the node.
* @param functions - The available functions for evaluation.
* @param values - The current values for evaluation.
* @returns The attribute value.
* @memberof Node
*/
evaluate(functions: Record<string, any>, values: Record<string, any>): any;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof Node
*/
toArray(): any[];
/**
* Dumps the node as a string.
* @returns The dumped string representation.
* @memberof Node
*/
dump(): string;
/**
* Escapes a string for use in dump output.
* @param value - The string to escape.
* @returns The escaped string.
* @memberof Node
*/
protected dumpString(value: string): string;
/**
* Determines whether an array is a hash (non-sequential keys).
* @param value - The array to check.
* @returns True if the array is a hash, false otherwise.
* @memberof Node
*/
protected isHash(value: Record<string | number, any>): boolean;
}
/**
* Represents a compiler for an expression language.
* @class Compiler
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class Compiler {
private readonly functions;
private source;
constructor(functions: Record<string, any>);
/**
* Gets function
* @param name
* @returns function
* @memberof Compiler
*/
getFunction(name: string): any;
/**
* Gets the current source code after compilation.
* @returns string
* @memberof Compiler
*/
getSource(): string;
/**
* Resets the state of the compiler.
* @returns this
* @memberof Compiler
*/
reset(): this;
/**
* Compiles a node.
* @returns this
* @memberof Compiler
*/
compile(node: Node): this;
subcompile(node: Node): string;
/**
* Adds a raw string to the compiled code.
* @returns this
* @memberof Compiler
*/
raw(string: string): this;
/**
* Adds a quoted string to the compiled code.
* @returns this
* @memberof Compiler
*/
string(value: string): this;
/**
* Returns a representation of a given value.
* @returns this
* @memberof Compiler
*/
repr(value: any, isIdentifier?: boolean): this;
}
/**
* Represents an array-like structure of an abstract syntax tree (AST) in the expression language.
* @class ArrayNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class ArrayNode extends Node {
protected index: number;
protected keyIndex: number;
protected arrayNodeType: 'Array' | 'Object';
constructor();
/**
* Adds an element to the node.
* @param value - The value node to add.
* @param key - Optional key node.
* @memberof ArrayNode
*/
addElement(value: Node, key?: Node | null): void;
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof ArrayNode
*/
compile(compiler: Compiler): void;
/**
* Evaluates the node.
* @param functions - The available functions for evaluation.
* @param values - The current values for evaluation.
* @returns The evaluated value.
* @memberof ArrayNode
*/
evaluate(functions: Record<string, any>, values: Record<string, any>): any[] | Record<any, any>;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof ArrayNode
*/
toArray(): (string | Node)[];
/**
* Retrieves key-value pairs from the node.
* @returns An array of key-value pair objects.
* @memberof ArrayNode
*/
protected getKeyValuePairs(): {
key: Node;
value: Node;
}[];
/**
* Compiles the node's arguments.
* @param compiler - The Compiler instance.
* @param withKeys - Whether to include keys in the compiled output.
* @memberof ArrayNode
*/
protected compileArguments(compiler: Compiler, withKeys?: boolean): void;
}
/**
* Represents a node for arguments of an abstract syntax tree (AST) in the expression language.
* @class ArgumentsNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class ArgumentsNode extends ArrayNode {
/**
* Compiles the arguments
* @param compiler - The Compiler instance to compile the node.
* @memberof ArgumentsNode
*/
compile(compiler: Compiler): void;
/**
* Converts the arguments node into an array representation.
* @returns An array of the node's arguments.
* @memberof ArgumentsNode
*/
toArray(): (string | Node)[];
}
/**
* Represents a binary node in an abstract syntax tree (AST) for an expression language.
* @class BinaryNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class BinaryNode extends Node {
private static readonly OPERATORS;
private static readonly FUNCTIONS;
constructor(operator: string, left: Node, right: Node);
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof BinaryNode
*/
compile(compiler: Compiler): void;
/**
* Evaluates the node.
* @param functions - The available functions for evaluation.
* @param values - The current values for evaluation.
* @returns The evaluated value.
* @memberof ArrayNode
*/
evaluate(functions: Record<string, any>, values: Record<string, any>): any;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof BinaryNode
*/
toArray(): (string | Node)[];
/**
* Evaluates matches
* @param regexp
* @param str
* @returns true if matches
* @memberof BinaryNode
*/
private evaluateMatches;
private pow;
private range;
private inArray;
private notInArray;
private strContains;
private strStartsWith;
private strEndsWith;
}
/**
* Represents a conditional node in an abstract syntax tree (AST) for an expression language.
* @class ConditionalNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class ConditionalNode extends Node {
constructor(expr1: Node, expr2: Node, expr3: Node);
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof ConditionalNode
*/
compile(compiler: Compiler): void;
/**
* Evaluates the node.
* @param functions - The available functions for evaluation.
* @param values - The current values for evaluation.
* @returns The evaluated value.
* @memberof ConditionalNode
*/
evaluate(functions: Record<string, any>, values: Record<string, any>): any;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof ConditionalNode
*/
toArray(): (string | Node)[];
}
/**
* Represents a constant node in an abstract syntax tree (AST) for an expression language.
* @class ConstantNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class ConstantNode extends Node {
isNullSafe: boolean;
isIdentifier: boolean;
constructor(value: any, isIdentifier?: boolean, isNullSafe?: boolean);
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof ConstantNode
*/
compile(compiler: Compiler): void;
/**
* Evaluates the node.
* @param _functions - The available functions for evaluation.
* @param _values - The current values for evaluation.
* @returns The attribute value.
* @memberof ConstantNode
*/
evaluate(_functions?: Record<string, any>, _values?: Record<string, any>): any;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof ConstantNode
*/
toArray(): (string | Node | number | bigint)[];
}
/**
* Represents a function node in an abstract syntax tree (AST) for an expression language.
* @class FunctionNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class FunctionNode extends Node {
constructor(name: string | number | null, argumentsNode: Node);
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof FunctionNode
*/
compile(compiler: Compiler): void;
/**
* Evaluates the node.
* @param functions - The available functions for evaluation.
* @param values - The current values for evaluation.
* @returns The evaluated value.
* @memberof FunctionNode
*/
evaluate(functions: Record<string, any>, values: Record<string, any>): any;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof FunctionNode
*/
toArray(): (string | number | Node)[];
}
/**
* Represents a attribute node in an abstract syntax tree (AST) for an expression language.
* @class GetAttrNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class GetAttrNode extends Node {
static readonly PROPERTY_CALL = 1;
static readonly METHOD_CALL = 2;
static readonly ARRAY_CALL = 3;
constructor(node: Node, attribute: Node, argumentsNode: ArrayNode, type: number);
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof GetAttrNode
*/
compile(compiler: Compiler): void;
/**
* Evaluates the node.
* @param functions - The available functions for evaluation.
* @param values - The current values for evaluation.
* @returns The evaluated value.
* @memberof GetAttrNode
*/
evaluate(functions: Record<string, any>, values: Record<string, any>): any;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof GetAttrNode
*/
toArray(): (string | Node)[];
/**
* Determines short circuited
* @returns true if short circuited
* @memberof GetAttrNode
*/
private isShortCircuited;
}
/**
* Represents a name node in an abstract syntax tree (AST) for an expression language.
* @class NameNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class NameNode extends Node {
constructor(name: string | number | null);
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof NameNode
*/
compile(compile: Compiler): void;
/**
* Evaluates the node.
* @param _functions - The available functions for evaluation.
* @param values - The current values for evaluation.
* @returns The attribute value.
* @memberof NameNode
*/
evaluate(_functions: Record<string, any>, values: Record<string, any>): any;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof NameNode
*/
toArray(): string[];
}
/**
* Represents a null-coalesce in an abstract syntax tree (AST) for an expression language.
* @class NullCoalesceNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class NullCoalesceNode extends Node {
constructor(expr1: Node, expr2: Node);
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof NullCoalesceNode
*/
compile(compiler: Compiler): void;
/**
* Evaluates the node.
* @param functions - The available functions for evaluation.
* @param values - The current values for evaluation.
* @returns The attribute value.
* @memberof NullCoalesceNode
*/
evaluate(functions: Record<string, any>, values: Record<string, any>): any;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof NullCoalesceNode
*/
toArray(): (string | Node)[];
/**
* Adds null coalesce attribute to get attr nodes
* @param node
* @returns null coalesce attribute to get attr nodes
* @memberof NullCoalesceNode
*/
private addNullCoalesceAttributeToGetAttrNodes;
}
/**
* Represents a null-coalesced-name in an abstract syntax tree (AST) for an expression language.
* @class NullCoalescedNameNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class NullCoalescedNameNode extends Node {
constructor(name: string | number | null);
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof NullCoalescedNameNode
*/
compile(compiler: Compiler): void;
/**
* Evaluates the node.
* @param _functions - The available functions for evaluation.
* @param _values - The current values for evaluation.
* @returns null.
* @memberof NullCoalescedNameNode
*/
evaluate(_functions: Record<string, any>, _values: Record<string, any>): null;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof NullCoalescedNameNode
*/
toArray(): string[];
}
/**
* Represents a unary node in an abstract syntax tree (AST) for an expression language.
* @class UnaryNode
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class UnaryNode extends Node {
static readonly OPERATORS: Record<string, string>;
constructor(operator: string | number | null, node: Node);
/**
* Compiles the node.
* @param compiler - The Compiler instance.
* @memberof UnaryNode
*/
compile(compiler: Compiler): void;
/**
* Evaluates the node.
* @param functions - The available functions for evaluation.
* @param values - The current values for evaluation.
* @returns The attribute value.
* @memberof UnaryNode
*/
evaluate(functions: Record<string, any>, values: Record<string, any>): any;
/**
* Converts the node to an array representation.
* @returns The array representation of the node.
* @memberof UnaryNode
*/
toArray(): (string | Node)[];
}
/**
* Represents an expression.
* @class Expression
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class Expression {
protected expression: string;
constructor(expression: string);
/**
* Gets the expression.
* @returns The string representation of the expression
* @memberof Expression
*/
toString(): string;
}
/**
* Represents an expression function in an expression language.
* @class ExpressionFunction
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
type Callable = (...args: any[]) => any;
declare class ExpressionFunction {
private readonly name;
private readonly compiler;
private readonly evaluator;
constructor(name: string, compiler: Callable, evaluator: Callable);
/**
* Creates an ExpressionFunction from a JavaScript function name.
* @param jsFunctionName The JavaScript function name
* @param expressionFunctionName The expression function name (optional)
* @throws Error if the JavaScript function does not exist.
* @memberof ExpressionFunction
*/
static fromJs(jsFunctionName: string, customFunction?: Callable, expressionFunctionName?: string): ExpressionFunction;
/**
* Gets name
* @returns name
* @memberof ExpressionFunction
*/
getName(): string;
/**
* Gets compiler
* @returns compiler
* @memberof ExpressionFunction
*/
getCompiler(): Callable;
/**
* Gets evaluator
* @returns evaluator
* @memberof ExpressionFunction
*/
getEvaluator(): Callable;
/**
* Resolves js function
* @param jsFunctionName
* @returns js function
* @memberof ExpressionFunction
*/
protected static resolveJsFunction(jsFunctionName: string): unknown;
}
/**
* Represents an already parsed expression.
* @class ParsedExpression
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class ParsedExpression extends Expression {
private readonly nodes;
constructor(expression: string, nodes: Node);
/**
* Gets nodes
* @returns nodes
* @memberof ParsedExpression
*/
getNodes(): Node;
}
interface ExpressionFunctionProvider {
getFunctions(): ExpressionFunction[];
}
/**
* Represents an expression language.
* @class ExpressionLanguage
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class ExpressionLanguage {
readonly cache: LRUCache<string, ParsedExpression>;
private lexer?;
private parser?;
private compiler?;
private functions;
constructor(cache?: LRUCache<string, ParsedExpression>, providers?: Iterable<ExpressionFunctionProvider>);
/**
* Compiles an expression source code.
* @param expression
* @param names
* @returns compile
* @memberof ExpressionLanguage
*/
compile(expression: Expression | string, names: (string | Record<string, any>)[]): string;
/**
* Evaluates an expression.
* @param expression
* @param values
* @returns evaluate
* @memberof ExpressionLanguage
*/
evaluate(expression: Expression | string, values?: Record<string, any>): ParsedExpression;
/**
* Parses an expression.
* @param expression
* @param names
* @param [flags]
* @returns parse
* @memberof ExpressionLanguage
*/
parse(expression: Expression | string, names: (string | Record<string, any>)[], flags?: number): ParsedExpression;
/**
* Validates the syntax of an expression.
* @param expression
* @param names
* @param [flags]
* @returns lint
* @memberof ExpressionLanguage
*/
lint(expression: Expression | string, names: string[] | null, flags?: number): void;
/**
* Registers a function.
* @param name
* @param expressionFn
* @memberof ExpressionLanguage
*/
register(name: string, expressionFn: ExpressionFunction): void;
/**
* Adds function.
* @param functionObj
* @memberof ExpressionLanguage
*/
addFunction(functionObj: ExpressionFunction): void;
/**
* Registers provider.
* @param provider
* @memberof ExpressionLanguage
*/
registerProvider(provider: ExpressionFunctionProvider): void;
/**
* Registers functions.
* @memberof ExpressionLanguage
*/
private registerFunctions;
/**
* Gets the lexer.
* @returns lexer
* @memberof ExpressionLanguage
*/
private getLexer;
/**
* Gets the parser.
* @returns parser
* @memberof ExpressionLanguage
*/
private getParser;
/**
* Gets the compiler
* @returns compiler
* @memberof ExpressionLanguage
*/
private getCompiler;
}
/**
* Represents a token.
* @class Token
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class Token {
type: string;
value: string | number | null;
cursor?: number | undefined;
static readonly EOF_TYPE = "end of expression";
static readonly NAME_TYPE = "name";
static readonly NUMBER_TYPE = "number";
static readonly STRING_TYPE = "string";
static readonly OPERATOR_TYPE = "operator";
static readonly PUNCTUATION_TYPE = "punctuation";
constructor(type: string, value: string | number | null, cursor?: number | undefined);
/**
* A string representation of the token
* @returns string
* @memberof Token
*/
toString(): string;
/**
* Tests token for type and value
* @param type
* @param [value]
* @returns true if test
* @memberof Token
*/
test(type: string, value?: string | null): boolean;
}
/**
* Represents a token stream.
* @class TokenStream
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class TokenStream {
readonly tokens: Token[];
readonly expression: string;
current: Token;
position: number;
constructor(tokens: Token[], expression?: string);
/**
* Returns a string representation of the token stream.
* @returns string
* @memberof TokenStream
*/
toString(): string;
/**
* Sets the pointer to the next token and updates the current token.
* @memberof TokenStream
*/
next(): void;
/**
* Checks if the current token matches the expected type and value.
* Throws an error if it doesn't.
* @param type
* @param [value]
* @param [message]
* @memberof TokenStream
*/
expect(type: string, value?: string | null, message?: string | null): void;
/**
* Checks if the end of the token stream is reached.
* @returns true if eof
* @memberof TokenStream
*/
isEOF(): boolean;
/**
* Returns the original expression for debugging or internal use.
* @returns expression
* @memberof TokenStream
*/
getExpression(): string;
}
/**
* Represents a lexer for an expression language.
* @class Lexer
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class Lexer {
private static readonly OPERATORS;
private static readonly NUMBER_REGEX;
private static readonly STRING_REGEX;
private static readonly COMMENT_REGEX;
private static readonly NAME_REGEX;
/**
* Tokenizes an expression.
* @param expression
* @returns tokenize
* @throws SyntaxError
* @memberof Lexer
*/
tokenize(expression: string): TokenStream;
/**
* Extracts the operator from the given string.
* @private
* @param {string} str
* @param {string} originalExpression
* @param {number} cursor
* @return {*} {(string | null)}
* @memberof Lexer
*/
private extractOperator;
}
/**
* Represents a parser for an expression language.
* @class Parser
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
type NameType = string | number | Record<string, any>;
declare class Parser {
private readonly functions;
static readonly OPERATOR_LEFT = 1;
static readonly OPERATOR_RIGHT = 2;
static readonly IGNORE_UNKNOWN_VARIABLES = 1;
static readonly IGNORE_UNKNOWN_FUNCTIONS = 2;
private static readonly unaryOperators;
private static readonly binaryOperators;
private stream;
private names;
private flags;
constructor(functions: Record<string, any>);
/**
* Converts a token stream to a node tree.
* @param stream
* @param [names]
* @param [flags]
* @returns parse
* @throws SyntaxError
* @memberof Parser
*/
parse(stream: TokenStream, names?: NameType[], flags?: number): Node;
/**
* Validates the syntax of an expression.
* The syntax of the passed expression will be checked, but not parsed.
* If you want to skip checking dynamic variable names, pass `Parser.IGNORE_UNKNOWN_VARIABLES` instead of the array.
* @param stream
* @param [names]
* @param [flags]
* @throws SyntaxError
* @memberof Parser
*/
lint(stream: TokenStream, names?: string[] | null, flags?: number): void;
/**
* Parses the expression
* @param [precedence]
* @returns node expression
* @memberof Parser
*/
parseExpression(precedence?: number): Node;
/**
* Parses primary expression
* @returns primary expression
* @memberof Parser
*/
parsePrimaryExpression(): Node;
/**
* Parses array expression
* @returns array expression
* @memberof Parser
*/
parseArrayExpression(): Node;
/**
* Parses hash expression
* @returns hash expression
* @memberof Parser
*/
parseHashExpression(): Node;
/**
* Parses postfix expression
* @param node
* @returns postfix expression
* @memberof Parser
*/
parsePostfixExpression(node: Node): Node;
/**
* Parses arguments
* @returns arguments
* @memberof Parser
*/
parseArguments(): Node;
/**
* Parse the given expression
* @param stream
* @param names
* @param flags
* @returns parse
* @throws SyntaxError
* @memberof Parse
*/
private doParse;
/**
* Gets the primary node
* @returns primary node
* @memberof Parse
*/
private getPrimary;
/**
* Parses conditional expression
* @param expr
* @returns conditional expression
* @memberof Parser
*/
private parseConditionalExpression;
}
/**
* Represents an already serialized parsed expression.
* @class SerializedParsedExpression
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class SerializedParsedExpression {
readonly expression: string;
private readonly nodes;
constructor(expression: string, nodes: string);
/**
* Deserializes and returns the nodes.
* @returns nodes
* @memberof SerializedParsedExpression
*/
getNodes(): Node;
}
/**
* Represents a syntax error in an expression.
* @author Andreas Nicolaou <anicolaou66@gmail.com>
*/
declare class SyntaxError extends Error {
constructor(message: string, cursor?: number | null, expression?: string, subject?: string | number | null, proposals?: (string | number)[] | null);
}
export { ArgumentsNode, ArrayNode, BinaryNode, Compiler, ConditionalNode, ConstantNode, Expression, ExpressionFunction, ExpressionLanguage, FunctionNode, GetAttrNode, Lexer, NameNode, Node, NullCoalesceNode, NullCoalescedNameNode, ParsedExpression, Parser, SerializedParsedExpression, SyntaxError, Token, TokenStream, UnaryNode };
export type { ExpressionFunctionProvider };