trader-server
Version:
OData server for testing strategies, simulating and real trading.
491 lines (470 loc) • 23 kB
text/typescript
import Utils from "./utils";
export enum TokenType {
Literal = "Literal",
ArrayOrObject = "ArrayOrObject",
Array = "Array",
Object = "Object",
Property = "Property",
Annotation = "Annotation",
Enum = "Enum",
EnumValue = "EnumValue",
EnumMemberValue = "EnumMemberValue",
Identifier = "Identifier",
QualifiedEntityTypeName = "QualifiedEntityTypeName",
QualifiedComplexTypeName = "QualifiedComplexTypeName",
ODataIdentifier = "ODataIdentifier",
Collection = "Collection",
NamespacePart = "NamespacePart",
EntitySetName = "EntitySetName",
SingletonEntity = "SingletonEntity",
EntityTypeName = "EntityTypeName",
ComplexTypeName = "ComplexTypeName",
TypeDefinitionName = "TypeDefinitionName",
EnumerationTypeName = "EnumerationTypeName",
EnumerationMember = "EnumerationMember",
TermName = "TermName",
PrimitiveProperty = "PrimitiveProperty",
PrimitiveKeyProperty = "PrimitiveKeyProperty",
PrimitiveNonKeyProperty = "PrimitiveNonKeyProperty",
PrimitiveCollectionProperty = "PrimitiveCollectionProperty",
ComplexProperty = "ComplexProperty",
ComplexCollectionProperty = "ComplexCollectionProperty",
StreamProperty = "StreamProperty",
NavigationProperty = "NavigationProperty",
EntityNavigationProperty = "EntityNavigationProperty",
EntityCollectionNavigationProperty = "EntityCollectionNavigationProperty",
Action = "Action",
ActionImport = "ActionImport",
Function = "Function",
EntityFunction = "EntityFunction",
EntityCollectionFunction = "EntityCollectionFunction",
ComplexFunction = "ComplexFunction",
ComplexCollectionFunction = "ComplexCollectionFunction",
PrimitiveFunction = "PrimitiveFunction",
PrimitiveCollectionFunction = "PrimitiveCollectionFunction",
EntityFunctionImport = "EntityFunctionImport",
EntityCollectionFunctionImport = "EntityCollectionFunctionImport",
ComplexFunctionImport = "ComplexFunctionImport",
ComplexCollectionFunctionImport = "ComplexCollectionFunctionImport",
PrimitiveFunctionImport = "PrimitiveFunctionImport",
PrimitiveCollectionFunctionImport = "PrimitiveCollectionFunctionImport",
CommonExpression = "CommonExpression",
AndExpression = "AndExpression",
OrExpression = "OrExpression",
EqualsExpression = "EqualsExpression",
NotEqualsExpression = "NotEqualsExpression",
LesserThanExpression = "LesserThanExpression",
LesserOrEqualsExpression = "LesserOrEqualsExpression",
GreaterThanExpression = "GreaterThanExpression",
GreaterOrEqualsExpression = "GreaterOrEqualsExpression",
HasExpression = "HasExpression",
AddExpression = "AddExpression",
SubExpression = "SubExpression",
MulExpression = "MulExpression",
DivExpression = "DivExpression",
ModExpression = "ModExpression",
NotExpression = "NotExpression",
BoolParenExpression = "BoolParenExpression",
ParenExpression = "ParenExpression",
MethodCallExpression = "MethodCallExpression",
IsOfExpression = "IsOfExpression",
CastExpression = "CastExpression",
NegateExpression = "NegateExpression",
FirstMemberExpression = "FirstMemberExpression",
MemberExpression = "MemberExpression",
PropertyPathExpression = "PropertyPathExpression",
ImplicitVariableExpression = "ImplicitVariableExpression",
LambdaVariable = "LambdaVariable",
LambdaVariableExpression = "LambdaVariableExpression",
LambdaPredicateExpression = "LambdaPredicateExpression",
AnyExpression = "AnyExpression",
AllExpression = "AllExpression",
CollectionNavigationExpression = "CollectionNavigationExpression",
SimpleKey = "SimpleKey",
CompoundKey = "CompoundKey",
KeyValuePair = "KeyValuePair",
KeyPropertyValue = "KeyPropertyValue",
KeyPropertyAlias = "KeyPropertyAlias",
SingleNavigationExpression = "SingleNavigationExpression",
CollectionPathExpression = "CollectionPathExpression",
ComplexPathExpression = "ComplexPathExpression",
SinglePathExpression = "SinglePathExpression",
FunctionExpression = "FunctionExpression",
FunctionExpressionParameters = "FunctionExpressionParameters",
FunctionExpressionParameter = "FunctionExpressionParameter",
ParameterName = "ParameterName",
ParameterAlias = "ParameterAlias",
ParameterValue = "ParameterValue",
CountExpression = "CountExpression",
RefExpression = "RefExpression",
ValueExpression = "ValueExpression",
RootExpression = "RootExpression",
QueryOptions = "QueryOptions",
CustomQueryOption = "CustomQueryOption",
Expand = "Expand",
ExpandItem = "ExpandItem",
ExpandPath = "ExpandPath",
ExpandCountOption = "ExpandCountOption",
ExpandRefOption = "ExpandRefOption",
ExpandOption = "ExpandOption",
Levels = "Levels",
Search = "Search",
SearchExpression = "SearchExpression",
SearchParenExpression = "SearchParenExpression",
SearchNotExpression = "SearchNotExpression",
SearchOrExpression = "SearchOrExpression",
SearchAndExpression = "SearchAndExpression",
SearchTerm = "SearchTerm",
SearchPhrase = "SearchPhrase",
SearchWord = "SearchWord",
Filter = "Filter",
OrderBy = "OrderBy",
OrderByItem = "OrderByItem",
Skip = "Skip",
Top = "Top",
Format = "Format",
InlineCount = "InlineCount",
Select = "Select",
SelectItem = "SelectItem",
SelectPath = "SelectPath",
AliasAndValue = "AliasAndValue",
SkipToken = "SkipToken",
Id = "Id",
Crossjoin = "Crossjoin",
AllResource = "AllResource",
ActionImportCall = "ActionImportCall",
FunctionImportCall = "FunctionImportCall",
EntityCollectionFunctionImportCall = "EntityCollectionFunctionImportCall",
EntityFunctionImportCall = "EntityFunctionImportCall",
ComplexCollectionFunctionImportCall = "ComplexCollectionFunctionImportCall",
ComplexFunctionImportCall = "ComplexFunctionImportCall",
PrimitiveCollectionFunctionImportCall = "PrimitiveCollectionFunctionImportCall",
PrimitiveFunctionImportCall = "PrimitiveFunctionImportCall",
FunctionParameters = "FunctionParameters",
FunctionParameter = "FunctionParameter",
ResourcePath = "ResourcePath",
CollectionNavigation = "CollectionNavigation",
CollectionNavigationPath = "CollectionNavigationPath",
SingleNavigation = "SingleNavigation",
PropertyPath = "PropertyPath",
ComplexPath = "ComplexPath",
BoundOperation = "BoundOperation",
BoundActionCall = "BoundActionCall",
BoundEntityFunctionCall = "BoundEntityFunctionCall",
BoundEntityCollectionFunctionCall = "BoundEntityCollectionFunctionCall",
BoundComplexFunctionCall = "BoundComplexFunctionCall",
BoundComplexCollectionFunctionCall = "BoundComplexCollectionFunctionCall",
BoundPrimitiveFunctionCall = "BoundPrimitiveFunctionCall",
BoundPrimitiveCollectionFunctionCall = "BoundPrimitiveCollectionFunctionCall",
ODataUri = "ODataUri",
Batch = "Batch",
Entity = "Entity",
Metadata = "Metadata"
}
export const LexerTokenType = TokenType;
export type LexerTokenType = TokenType;
export class Token {
position: number;
next: number;
value: any;
type: TokenType;
raw: string;
metadata: any;
constructor(token) {
this.position = token.position;
this.next = token.next;
this.value = token.value;
this.type = token.type;
this.raw = token.raw;
if (token.metadata) this.metadata = token.metadata;
}
}
export const LexerToken = Token;
export type LexerToken = Token;
export namespace Lexer {
export type Token = LexerToken;
export const Token: typeof LexerToken = exports.Token;
export type TokenType = LexerTokenType;
export const TokenType: typeof LexerTokenType = exports.TokenType;
export function tokenize(value: Utils.SourceArray, index: number, next: number, tokenValue: any, tokenType: TokenType, metadataContextContainer?: Token): Token {
let token = new exports.Token({
position: index,
next: next,
value: tokenValue,
type: tokenType,
raw: Utils.stringify(value, index, next)
});
if (metadataContextContainer && metadataContextContainer.metadata) {
token.metadata = metadataContextContainer.metadata;
delete metadataContextContainer.metadata;
}
return token;
}
export function clone(token): Token {
return new exports.Token({
position: token.position,
next: token.next,
value: token.value,
type: token.type,
raw: token.raw
});
}
// core definitions
export function ALPHA(value: number): boolean { return (value >= 0x41 && value <= 0x5a) || (value >= 0x61 && value <= 0x7a) || value >= 0x80; }
export function DIGIT(value: number): boolean { return (value >= 0x30 && value <= 0x39); }
export function HEXDIG(value: number): boolean { return Lexer.DIGIT(value) || Lexer.AtoF(value); }
export function AtoF(value: number): boolean { return (value >= 0x41 && value <= 0x46) || (value >= 0x61 && value <= 0x66); }
export function DQUOTE(value: number): boolean { return value === 0x22; }
export function SP(value: number): boolean { return value === 0x20; }
export function HTAB(value: number): boolean { return value === 0x09; }
export function VCHAR(value: number): boolean { return value >= 0x21 && value <= 0x7e; }
// punctuation
export function whitespaceLength(value, index) {
if (Utils.equals(value, index, "%20") || Utils.equals(value, index, "%09")) return 3;
else if (Lexer.SP(value[index]) || Lexer.HTAB(value[index]) || value[index] === 0x20 || value[index] === 0x09) return 1;
}
export function OWS(value: Utils.SourceArray, index: number): number {
index = index || 0;
let inc = Lexer.whitespaceLength(value, index);
while (inc) {
index += inc;
inc = Lexer.whitespaceLength(value, index);
}
return index;
}
export function RWS(value: Utils.SourceArray, index: number): number {
return Lexer.OWS(value, index);
}
export function BWS(value: Utils.SourceArray, index: number): number {
return Lexer.OWS(value, index);
}
export function AT(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x40) return index + 1;
else if (Utils.equals(value, index, "%40")) return index + 3;
}
export function COLON(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x3a) return index + 1;
else if (Utils.equals(value, index, "%3A")) return index + 3;
}
export function COMMA(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x2c) return index + 1;
else if (Utils.equals(value, index, "%2C")) return index + 3;
}
export function EQ(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x3d) return index + 1;
}
export function SIGN(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x2b || value[index] === 0x2d) return index + 1;
else if (Utils.equals(value, index, "%2B")) return index + 3;
}
export function SEMI(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x3b) return index + 1;
else if (Utils.equals(value, index, "%3B")) return index + 3;
}
export function STAR(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x2a) return index + 1;
else if (Utils.equals(value, index, "%2A")) return index + 3;
}
export function SQUOTE(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x27) return index + 1;
else if (Utils.equals(value, index, "%27")) return index + 3;
}
export function OPEN(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x28) return index + 1;
else if (Utils.equals(value, index, "%28")) return index + 3;
}
export function CLOSE(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x29) return index + 1;
else if (Utils.equals(value, index, "%29")) return index + 3;
}
// unreserved ALPHA / DIGIT / "-" / "." / "_" / "~"
export function unreserved(value: number): boolean { return Lexer.ALPHA(value) || Lexer.DIGIT(value) || value === 0x2d || value === 0x2e || value === 0x5f || value === 0x7e; }
// other-delims "!" / "(" / ")" / "*" / "+" / "," / ";"
export function otherDelims(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x21 || value[index] === 0x2b) return index + 1;
else return Lexer.OPEN(value, index) || Lexer.CLOSE(value, index) || Lexer.STAR(value, index) || Lexer.COMMA(value, index) || Lexer.SEMI(value, index);
}
// sub-delims = "$" / "&" / "'" / "=" / other-delims
export function subDelims(value: Utils.SourceArray, index: number): number {
if (value[index] === 0x24 || value[index] === 0x26) return index + 1;
else return Lexer.SQUOTE(value, index) || Lexer.EQ(value, index) || Lexer.otherDelims(value, index);
}
export function pctEncoded(value: Utils.SourceArray, index: number): number {
if (value[index] !== 0x25 || !Lexer.HEXDIG(value[index + 1]) || !Lexer.HEXDIG(value[index + 2])) return index;
return index + 3;
}
// pct-encoded-no-SQUOTE = "%" ( "0" / "1" / "3" / "4" / "5" / "6" / "8" / "9" / A-to-F ) HEXDIG
// / "%" "2" ( "0" / "1" / "2" / "3" / "4" / "5" / "6" / "8" / "9" / A-to-F )
export function pctEncodedNoSQUOTE(value: Utils.SourceArray, index: number): number {
if (Utils.equals(value, index, "%27")) return index;
return Lexer.pctEncoded(value, index);
}
export function pctEncodedUnescaped(value: Utils.SourceArray, index: number): number {
if (Utils.equals(value, index, "%22") ||
Utils.equals(value, index, "%3") ||
Utils.equals(value, index, "%4") ||
Utils.equals(value, index, "%5C")) return index;
return Lexer.pctEncoded(value, index);
}
export function pchar(value: Utils.SourceArray, index: number): number {
if (Lexer.unreserved(value[index])) return index + 1;
else return Lexer.subDelims(value, index) || Lexer.COLON(value, index) || Lexer.AT(value, index) || Lexer.pctEncoded(value, index) || index;
}
export function pcharNoSQUOTE(value: Utils.SourceArray, index: number): number {
if (Lexer.unreserved(value[index]) || value[index] === 0x24 || value[index] === 0x26) return index + 1;
else return Lexer.otherDelims(value, index) || Lexer.EQ(value, index) || Lexer.COLON(value, index) || Lexer.AT(value, index) || Lexer.pctEncodedNoSQUOTE(value, index) || index;
}
export function qcharNoAMP(value: Utils.SourceArray, index: number): number {
if (Lexer.unreserved(value[index]) || value[index] === 0x3a || value[index] === 0x40 || value[index] === 0x2f || value[index] === 0x3f || value[index] === 0x24 || value[index] === 0x27 || value[index] === 0x3d) return index + 1;
else return Lexer.pctEncoded(value, index) || Lexer.otherDelims(value, index) || index;
}
export function qcharNoAMPDQUOTE(value: Utils.SourceArray, index: number): number {
index = Lexer.BWS(value, index);
if (Lexer.unreserved(value[index]) || value[index] === 0x3a || value[index] === 0x40 || value[index] === 0x2f || value[index] === 0x3f || value[index] === 0x24 || value[index] === 0x27 || value[index] === 0x3d) return index + 1;
else return Lexer.otherDelims(value, index) || Lexer.pctEncodedUnescaped(value, index);
}
// export function pchar(value:number):boolean { return unreserved(value) || otherDelims(value) || value == 0x24 || value == 0x26 || EQ(value) || COLON(value) || AT(value); }
export function base64char(value: number): boolean { return Lexer.ALPHA(value) || Lexer.DIGIT(value) || value === 0x2d || value === 0x5f; }
export function base64b16(value: Utils.SourceArray, index: number): number {
let start = index;
if (!Lexer.base64char(value[index]) && !Lexer.base64char(value[index + 1])) return start;
index += 2;
if (!Utils.is(value[index], "AEIMQUYcgkosw048")) return start;
index++;
if (value[index] === 0x3d) index++;
return index;
}
export function base64b8(value: Utils.SourceArray, index: number): number {
let start = index;
if (!Lexer.base64char(value[index])) return start;
index++;
if (value[index] !== 0x41 || value[index] !== 0x51 || value[index] !== 0x67 || value[index] !== 0x77) return start;
index++;
if (value[index] === 0x3d && value[index + 1] === 0x3d) index += 2;
return index;
}
export function nanInfinity(value: Utils.SourceArray, index: number): number {
return Utils.equals(value, index, "NaN") || Utils.equals(value, index, "-INF") || Utils.equals(value, index, "INF");
}
export function oneToNine(value: number): boolean { return value !== 0x30 && Lexer.DIGIT(value); }
export function zeroToFiftyNine(value: Utils.SourceArray, index: number): number {
if (value[index] >= 0x30 && value[index] <= 0x35 && Lexer.DIGIT(value[index + 1])) return index + 2;
return index;
}
export function year(value: Utils.SourceArray, index: number): number {
let start = index;
let end = index;
if (value[index] === 0x2d) index++;
if ((value[index] === 0x30 && (end = Utils.required(value, index + 1, Lexer.DIGIT, 3, 3))) ||
(Lexer.oneToNine(value[index]) && (end = Utils.required(value, index + 1, Lexer.DIGIT, 3)))) return end;
return start;
}
export function month(value: Utils.SourceArray, index: number): number {
if ((value[index] === 0x30 && Lexer.oneToNine(value[index + 1])) ||
(value[index] === 0x31 && value[index + 1] >= 0x30 && value[index + 1] <= 0x32)) return index + 2;
return index;
}
export function day(value: Utils.SourceArray, index: number): number {
if ((value[index] === 0x30 && Lexer.oneToNine(value[index + 1])) ||
((value[index] === 0x31 || value[index] === 0x32) && Lexer.DIGIT(value[index + 1])) ||
(value[index] === 0x33 && (value[index + 1] === 0x30 || value[index + 1] === 0x31))) return index + 2;
return index;
}
export function hour(value: Utils.SourceArray, index: number): number {
if (((value[index] === 0x30 || value[index] === 0x31) && Lexer.DIGIT(value[index + 1])) ||
(value[index] === 0x32 && (value[index + 1] === 0x30 || value[index + 1] === 0x31 || value[index + 1] === 0x32 || value[index + 1] === 0x33))) return index + 2;
return index;
}
export function minute(value: Utils.SourceArray, index: number): number {
return Lexer.zeroToFiftyNine(value, index);
}
export function second(value: Utils.SourceArray, index: number): number {
return Lexer.zeroToFiftyNine(value, index);
}
export function fractionalSeconds(value: Utils.SourceArray, index: number): number {
return Utils.required(value, index, DIGIT, 1, 12);
}
export function geographyPrefix(value: Utils.SourceArray, index: number): number {
return Utils.equals(value, index, "geography") ? index + 9 : index;
}
export function geometryPrefix(value: Utils.SourceArray, index: number): number {
return Utils.equals(value, index, "geometry") ? index + 8 : index;
}
export function identifierLeadingCharacter(value: number): boolean {
return Lexer.ALPHA(value) || value === 0x5f;
}
export function identifierCharacter(value: number): boolean {
return Lexer.identifierLeadingCharacter(value) || Lexer.DIGIT(value);
}
export function beginObject(value: Utils.SourceArray, index: number): number {
let bws = Lexer.BWS(value, index);
let start = index;
index = bws;
if (Utils.equals(value, index, "{")) index++;
else if (Utils.equals(value, index, "%7B")) index += 3;
if (index === bws) return start;
bws = Lexer.BWS(value, index);
return bws;
}
export function endObject(value: Utils.SourceArray, index: number): number {
let bws = Lexer.BWS(value, index);
let start = index;
index = bws;
if (Utils.equals(value, index, "}")) index++;
else if (Utils.equals(value, index, "%7D")) index += 3;
if (index === bws) return start;
bws = Lexer.BWS(value, index);
return bws;
}
export function beginArray(value: Utils.SourceArray, index: number): number {
let bws = Lexer.BWS(value, index);
let start = index;
index = bws;
if (Utils.equals(value, index, "[")) index++;
else if (Utils.equals(value, index, "%5B")) index += 3;
if (index === bws) return start;
bws = Lexer.BWS(value, index);
return bws;
}
export function endArray(value: Utils.SourceArray, index: number): number {
let bws = Lexer.BWS(value, index);
let start = index;
index = bws;
if (Utils.equals(value, index, "]")) index++;
else if (Utils.equals(value, index, "%5D")) index += 3;
if (index === bws) return start;
bws = Lexer.BWS(value, index);
return bws;
}
export function quotationMark(value: Utils.SourceArray, index: number): number {
if (Lexer.DQUOTE(value[index])) return index + 1;
if (Utils.equals(value, index, "%22")) return index + 3;
return index;
}
export function nameSeparator(value: Utils.SourceArray, index: number): number {
let bws = Lexer.BWS(value, index);
let start = index;
index = bws;
let colon = Lexer.COLON(value, index);
if (!colon) return start;
index = colon;
bws = Lexer.BWS(value, index);
return bws;
}
export function valueSeparator(value: Utils.SourceArray, index: number): number {
let bws = Lexer.BWS(value, index);
let start = index;
index = bws;
let comma = Lexer.COMMA(value, index);
if (!comma) return start;
index = comma;
bws = Lexer.BWS(value, index);
return bws;
}
export function escape(value: Utils.SourceArray, index: number): number {
if (Utils.equals(value, index, "\\")) return index + 1;
if (Utils.equals(value, index, "%5C")) return index + 3;
return index;
}
}
export default Lexer;