coffee-lex
Version:
Stupid lexer for CoffeeScript.
314 lines (307 loc) • 10.3 kB
TypeScript
/**
* Represents a particular type of CoffeeScript code.
*/
declare enum SourceType {
AT = "AT",
BOOL = "BOOL",
BREAK = "BREAK",
CATCH = "CATCH",
CALL_END = "CALL_END",
CALL_START = "CALL_START",
CLASS = "CLASS",
COLON = "COLON",
COMMA = "COMMA",
COMMENT = "COMMENT",
CONTINUATION = "CONTINUATION",
CONTINUE = "CONTINUE",
CSX_BODY = "CSX_BODY",
CSX_CLOSE_TAG_START = "CSX_CLOSE_TAG_START",
CSX_CLOSE_TAG_END = "CSX_CLOSE_TAG_END",
CSX_OPEN_TAG_START = "CSX_OPEN_TAG_START",
CSX_OPEN_TAG_END = "CSX_OPEN_TAG_END",
CSX_SELF_CLOSING_TAG_END = "CSX_SELF_CLOSING_TAG_END",
DECREMENT = "DECREMENT",
DEFAULT = "DEFAULT",
DELETE = "DELETE",
DO = "DO",
DOT = "DOT",
DSTRING_START = "DSTRING_START",
DSTRING_END = "DSTRING_END",
ELSE = "ELSE",
EXPORT = "EXPORT",
EOF = "EOF",
EXISTENCE = "EXISTENCE",
EXTENDS = "EXTENDS",
FINALLY = "FINALLY",
FOR = "FOR",
FUNCTION = "FUNCTION",
HERECOMMENT = "HERECOMMENT",
HEREJS = "HEREJS",
HEREGEXP_COMMENT = "HEREGEXP_COMMENT",
HEREGEXP_START = "HEREGEXP_START",
HEREGEXP_END = "HEREGEXP_END",
IF = "IF",
IMPORT = "IMPORT",
INCREMENT = "INCREMENT",
INTERPOLATION_START = "INTERPOLATION_START",
INTERPOLATION_END = "INTERPOLATION_END",
JS = "JS",
LBRACE = "LBRACE",
LBRACKET = "LBRACKET",
LOOP = "LOOP",
LPAREN = "LPAREN",
NEW = "NEW",
NEWLINE = "NEWLINE",
NORMAL = "NORMAL",
NULL = "NULL",
NUMBER = "NUMBER",
OPERATOR = "OPERATOR",
OWN = "OWN",
PROTO = "PROTO",
RANGE = "RANGE",
REGEXP = "REGEXP",
RBRACE = "RBRACE",
RBRACKET = "RBRACKET",
RELATION = "RELATION",
RETURN = "RETURN",
RPAREN = "RPAREN",
SEMICOLON = "SEMICOLON",
SPACE = "SPACE",
SUPER = "SUPER",
SWITCH = "SWITCH",
SSTRING_START = "SSTRING_START",
SSTRING_END = "SSTRING_END",
STRING_CONTENT = "STRING_CONTENT",
STRING_LINE_SEPARATOR = "STRING_LINE_SEPARATOR",
STRING_PADDING = "STRING_PADDING",
TDSTRING_START = "TDSTRING_START",
TDSTRING_END = "TDSTRING_END",
THEN = "THEN",
THIS = "THIS",
THROW = "THROW",
TRY = "TRY",
TSSTRING_START = "TSSTRING_START",
TSSTRING_END = "TSSTRING_END",
UNDEFINED = "UNDEFINED",
UNKNOWN = "UNKNOWN",
WHEN = "WHEN",
WHILE = "WHILE",
IDENTIFIER = "IDENTIFIER",
YIELD = "YIELD",
YIELDFROM = "YIELDFROM"
}
/**
* Represents a change in source code type at a particular index.
*/
declare class SourceLocation {
readonly type: SourceType;
readonly index: number;
constructor(type: SourceType, index: number);
}
declare class SourceToken {
readonly type: SourceType;
readonly start: number;
readonly end: number;
constructor(type: SourceType, start: number, end: number);
}
/**
* Represents a token at a particular index within a list of tokens.
*/
declare class SourceTokenListIndex {
private _sourceTokenList;
private _index;
constructor(sourceTokenList: SourceTokenList, index: number);
/**
* Get a new index offset from this one, if the resulting offset is within
* the list range.
*/
advance(offset: number): SourceTokenListIndex | null;
/**
* Get the index of the token after this one, if it's not the last one.
*/
next(): SourceTokenListIndex | null;
/**
* Get the index of the token before this one, if it's not the first one.
*/
previous(): SourceTokenListIndex | null;
/**
* Determines whether this index comes before another.
*/
isBefore(other: SourceTokenListIndex): boolean;
/**
* Determines whether this index comes after another.
*/
isAfter(other: SourceTokenListIndex): boolean;
/**
* Compare this index to another, returning 0 for equality, a negative number
* if this is less than `other`, and a positive number otherwise.
*/
compare(other: SourceTokenListIndex): number;
/**
* Returns an int of the relative distance between this index and the other
* index (positive if the other one is later, negative if the other one is
* earlier).
*/
distance(other: SourceTokenListIndex): number;
}
declare type SourceTokenListIndexRange = [
SourceTokenListIndex,
SourceTokenListIndex
];
/**
* Represents a list of tokens and provides various utility functions for
* finding tokens within it.
*/
declare class SourceTokenList {
private _tokens;
private _indexCache;
private _indexBySourceIndex;
private _indexByStartSourceIndex;
private _indexByEndSourceIndex;
readonly length: number;
readonly startIndex: SourceTokenListIndex;
readonly endIndex: SourceTokenListIndex;
constructor(tokens: Array<SourceToken>);
/**
* Iterate over each token.
*/
forEach(iterator: (token: SourceToken, index: SourceTokenListIndex, list: SourceTokenList) => void): void;
/**
* Map each token to an element of an array.
*/
map<T>(mapper: (token: SourceToken, index: SourceTokenListIndex, list: SourceTokenList) => T): Array<T>;
/**
* Filter tokens by a predicate.
*/
filter(predicate: (token: SourceToken, index: SourceTokenListIndex, list: SourceTokenList) => boolean): SourceTokenList;
/**
* Get a slice of this token list using the given indexes.
*/
slice(start: SourceTokenListIndex, end: SourceTokenListIndex): SourceTokenList;
/**
* Get the token at the given index, if it exists.
*
* NOTE: The only value for which this should return `null` is this list's
* `endIndex`.
*/
tokenAtIndex(index: SourceTokenListIndex): SourceToken | null;
/**
* Get the range of tokens representing an interpolated string that contains
* the token at `index`. This will return the innermost interpolated string in
* the case of nesting.
*/
rangeOfInterpolatedStringTokensContainingTokenIndex(index: SourceTokenListIndex): SourceTokenListIndexRange | null;
/**
* Get the range of tokens starting with a token of type `startType` and
* ending one past a token of type `endType`, ensuring that the tokens match.
* That is, it ensures they are balanced and properly account for nesting.
* This range will contain `index`. If no such range can be found, `null` is
* returned.
*/
rangeOfMatchingTokensContainingTokenIndex(startType: SourceType, endType: SourceType, index: SourceTokenListIndex): SourceTokenListIndexRange | null;
/**
* Finds the index of the token whose source range includes the given index.
* If the given index does not correspond to the range of a token, returns
* null.
*/
indexOfTokenContainingSourceIndex(index: number): SourceTokenListIndex | null;
/**
* If the given source index lands on a token, return the index of that token.
* Otherwise, return the index of the previous token in the source code, or
* the first token if there is no previous token.
*/
indexOfTokenNearSourceIndex(index: number): SourceTokenListIndex;
/**
* Finds the index of the token whose source range starts at the given index.
*/
indexOfTokenStartingAtSourceIndex(index: number): SourceTokenListIndex | null;
/**
* Finds the index of the token whose source range ends at the given index.
*/
indexOfTokenEndingAtSourceIndex(index: number): SourceTokenListIndex | null;
/**
* Finds the index of the first token matching a predicate.
*/
indexOfTokenMatchingPredicate(predicate: (token: SourceToken) => boolean, start?: SourceTokenListIndex | null, end?: SourceTokenListIndex | null): SourceTokenListIndex | null;
/**
* Finds the index of the first token matching a predicate, traversing
* backwards.
*/
lastIndexOfTokenMatchingPredicate(predicate: (token: SourceToken) => boolean, start?: SourceTokenListIndex | null, end?: SourceTokenListIndex | null): SourceTokenListIndex | null;
/**
* Allow iterating over the tokens in this list using e.g. `for (… of …)`.
*/
[Symbol.iterator](): Iterator<SourceToken>;
/**
* @internal
*/
private _validateTokens;
/**
* @internal
*/
private _validateIndex;
/**
* @internal
*/
private _validateSourceIndex;
/**
* @internal
*/
private _getIndex;
/**
* Get the list of tokens.
*/
toArray(): Array<SourceToken>;
}
declare enum ContextType {
STRING = "STRING",
INTERPOLATION = "INTERPOLATION",
CSX_OPEN_TAG = "CSX_OPEN_TAG",
CSX_CLOSE_TAG = "CSX_CLOSE_TAG",
CSX_BODY = "CSX_BODY",
BRACE = "BRACE",
PAREN = "PAREN"
}
declare type Context = {
readonly type: ContextType.STRING;
readonly allowComments: boolean;
readonly allowInterpolations: boolean;
readonly endingDelimiter: string;
readonly endSourceType: SourceType;
} | {
readonly type: ContextType.INTERPOLATION;
readonly interpolationType: SourceType;
} | {
readonly type: ContextType.CSX_OPEN_TAG;
} | {
readonly type: ContextType.CSX_CLOSE_TAG;
} | {
readonly type: ContextType.CSX_BODY;
} | {
readonly type: ContextType.BRACE;
} | {
readonly type: ContextType.PAREN;
readonly sourceType: SourceType;
};
interface Options {
readonly useCS2: boolean;
}
declare const DEFAULT_OPTIONS: Options;
/**
* A lexer error at a specific location.
*/
declare class CoffeeLexError extends SyntaxError {
readonly index: number;
readonly context?: Context | undefined;
constructor(message: string, index: number, context?: Context | undefined);
}
/**
* Generate a list of tokens from CoffeeScript source code.
*/
declare function lex(source: string, options?: Options): SourceTokenList;
/**
* Provides a stream of source type change locations.
*/
declare function stream(source: string, index?: number, options?: Options): () => SourceLocation;
declare function consumeStream(lexer: () => SourceLocation): Array<SourceLocation>;
export { CoffeeLexError, DEFAULT_OPTIONS, Options, SourceLocation, SourceToken, SourceTokenList, SourceTokenListIndex, SourceTokenListIndexRange, SourceType, consumeStream, lex as default, lex, stream };