@wgslx/wgslx
Version:
Extended WebGPU shading language tools
167 lines (130 loc) • 3.62 kB
text/typescript
/** Json representation of the token. */
export interface TokenJson {
text?: string;
symbol?: string;
modifier?: string;
modifiedSymbol?: string;
source?: string;
destination?: string;
children?: TokenJson[];
}
export interface TokenRange {
file: string;
line: number;
column: number;
}
export class TokenOptions {
symbol?: string;
modifier?: string;
}
export class Token {
/** Execution unique identifier. */
id: number;
text?: string;
symbol?: string;
/** The method of grouping */
modifier?: string;
modifiedSymbol?: string;
source?: string;
destination?: string;
children?: Token[];
clone(): Token {
const token = new Token();
if (this.text) token.text = this.text;
if (this.symbol) token.symbol = this.symbol;
if (this.modifier) token.modifier = this.modifier;
if (this.modifiedSymbol) token.modifiedSymbol = this.modifiedSymbol;
if (this.source) token.source = this.source;
if (this.destination) token.destination = this.destination;
if (this.children) token.children = this.children; // shallow copy
return token;
}
toObject(): TokenJson {
const object: TokenJson = {};
if (this.source) object.source = this.source;
if (this.destination) object.destination = this.destination;
if (this.text) object.text = this.text;
if (this.symbol) object.symbol = this.symbol;
if (this.modifiedSymbol) object.modifiedSymbol = this.modifiedSymbol;
if (this.modifier) object.modifier = this.modifier;
if (this.children) object.children = this.children.map((t) => t.toObject());
return object;
}
toString(compact = false) {
if (this.children) {
const text = this.children
.map((m) => m?.toString())
.filter((t) => t)
.join(' ');
if (compact) {
return text.replace(
/([^\p{XID_Continue}] |[\p{XID_Continue}] (?![\p{XID_Continue}]))/gu,
(match: string) => match[0]
);
}
return text;
}
return this.text;
}
static text(text: string, source: string): Token {
const token = new Token();
token.source = source;
token.text = text;
return token;
}
static group(children: Token[], modifier: string, symbol?: string): Token {
const token = new Token();
token.children = children;
token.modifier = modifier;
if (symbol) {
token.symbol = symbol;
}
return token;
}
static modify(
children: Token[],
modifier: string,
modifiedSymbol?: string
): Token {
const token = new Token();
token.children = children;
token.modifier = modifier;
if (modifiedSymbol) {
token.modifiedSymbol = modifiedSymbol;
}
return token;
}
static symbol(token: Token, symbol: string): Token {
if (token.symbol === undefined) {
token.symbol = symbol;
return token;
}
const parent = new Token();
parent.children = [token];
parent.symbol = symbol;
return parent;
}
private static idCount = 0;
private constructor() {
this.id = ++Token.idCount;
}
}
/** Context for rule token matching. */
export class Multimap<TKey, TValue> {
readonly map = new Map<TKey, TValue[]>();
/** Gets a match for a position and rule in the cache. */
get(key: TKey): TValue[] {
return this.map.get(key) ?? [];
}
/** Sets a match for a position and rule in the cache. */
add(key: TKey, value: TValue) {
let list = this.map.get(key);
if (list) {
list.push(value);
} else {
list = [value];
this.map.set(key, list);
}
return list;
}
}