forked from olcxjas-softworks/LarpixClient
159 lines
4.2 KiB
TypeScript
159 lines
4.2 KiB
TypeScript
import {
|
|
cloneArr,
|
|
compact,
|
|
contains,
|
|
difference,
|
|
flatten,
|
|
forEach,
|
|
has,
|
|
isArray,
|
|
isEmpty,
|
|
map
|
|
} from "../utils/utils"
|
|
import { TokenType } from "../../api"
|
|
|
|
export function tokenStructuredMatcher(tokInstance, tokConstructor) {
|
|
const instanceType = tokInstance.tokenTypeIdx
|
|
if (instanceType === tokConstructor.tokenTypeIdx) {
|
|
return true
|
|
} else {
|
|
return (
|
|
tokConstructor.isParent === true &&
|
|
tokConstructor.categoryMatchesMap[instanceType] === true
|
|
)
|
|
}
|
|
}
|
|
|
|
// Optimized tokenMatcher in case our grammar does not use token categories
|
|
// Being so tiny it is much more likely to be in-lined and this avoid the function call overhead
|
|
export function tokenStructuredMatcherNoCategories(token, tokType) {
|
|
return token.tokenTypeIdx === tokType.tokenTypeIdx
|
|
}
|
|
|
|
export let tokenShortNameIdx = 1
|
|
export const tokenIdxToClass = {}
|
|
|
|
export function augmentTokenTypes(tokenTypes: TokenType[]): void {
|
|
// collect the parent Token Types as well.
|
|
let tokenTypesAndParents = expandCategories(tokenTypes)
|
|
|
|
// add required tokenType and categoryMatches properties
|
|
assignTokenDefaultProps(tokenTypesAndParents)
|
|
|
|
// fill up the categoryMatches
|
|
assignCategoriesMapProp(tokenTypesAndParents)
|
|
assignCategoriesTokensProp(tokenTypesAndParents)
|
|
|
|
forEach(tokenTypesAndParents, (tokType) => {
|
|
tokType.isParent = tokType.categoryMatches.length > 0
|
|
})
|
|
}
|
|
|
|
export function expandCategories(tokenTypes: TokenType[]): TokenType[] {
|
|
let result = cloneArr(tokenTypes)
|
|
|
|
let categories = tokenTypes
|
|
let searching = true
|
|
while (searching) {
|
|
categories = compact(
|
|
flatten(map(categories, (currTokType) => currTokType.CATEGORIES))
|
|
)
|
|
|
|
let newCategories = difference(categories, result)
|
|
|
|
result = result.concat(newCategories)
|
|
|
|
if (isEmpty(newCategories)) {
|
|
searching = false
|
|
} else {
|
|
categories = newCategories
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
export function assignTokenDefaultProps(tokenTypes: TokenType[]): void {
|
|
forEach(tokenTypes, (currTokType) => {
|
|
if (!hasShortKeyProperty(currTokType)) {
|
|
tokenIdxToClass[tokenShortNameIdx] = currTokType
|
|
;(<any>currTokType).tokenTypeIdx = tokenShortNameIdx++
|
|
}
|
|
|
|
// CATEGORIES? : TokenType | TokenType[]
|
|
if (
|
|
hasCategoriesProperty(currTokType) &&
|
|
!isArray(currTokType.CATEGORIES)
|
|
// &&
|
|
// !isUndefined(currTokType.CATEGORIES.PATTERN)
|
|
) {
|
|
currTokType.CATEGORIES = [currTokType.CATEGORIES]
|
|
}
|
|
|
|
if (!hasCategoriesProperty(currTokType)) {
|
|
currTokType.CATEGORIES = []
|
|
}
|
|
|
|
if (!hasExtendingTokensTypesProperty(currTokType)) {
|
|
currTokType.categoryMatches = []
|
|
}
|
|
|
|
if (!hasExtendingTokensTypesMapProperty(currTokType)) {
|
|
currTokType.categoryMatchesMap = {}
|
|
}
|
|
})
|
|
}
|
|
|
|
export function assignCategoriesTokensProp(tokenTypes: TokenType[]): void {
|
|
forEach(tokenTypes, (currTokType) => {
|
|
// avoid duplications
|
|
currTokType.categoryMatches = []
|
|
forEach(currTokType.categoryMatchesMap, (val, key) => {
|
|
currTokType.categoryMatches.push(tokenIdxToClass[key].tokenTypeIdx)
|
|
})
|
|
})
|
|
}
|
|
|
|
export function assignCategoriesMapProp(tokenTypes: TokenType[]): void {
|
|
forEach(tokenTypes, (currTokType) => {
|
|
singleAssignCategoriesToksMap([], currTokType)
|
|
})
|
|
}
|
|
|
|
export function singleAssignCategoriesToksMap(
|
|
path: TokenType[],
|
|
nextNode: TokenType
|
|
): void {
|
|
forEach(path, (pathNode) => {
|
|
nextNode.categoryMatchesMap[pathNode.tokenTypeIdx] = true
|
|
})
|
|
|
|
forEach(nextNode.CATEGORIES, (nextCategory) => {
|
|
const newPath = path.concat(nextNode)
|
|
// avoids infinite loops due to cyclic categories.
|
|
if (!contains(newPath, nextCategory)) {
|
|
singleAssignCategoriesToksMap(newPath, nextCategory)
|
|
}
|
|
})
|
|
}
|
|
|
|
export function hasShortKeyProperty(tokType: TokenType): boolean {
|
|
return has(tokType, "tokenTypeIdx")
|
|
}
|
|
|
|
export function hasCategoriesProperty(tokType: TokenType): boolean {
|
|
return has(tokType, "CATEGORIES")
|
|
}
|
|
|
|
export function hasExtendingTokensTypesProperty(tokType: TokenType): boolean {
|
|
return has(tokType, "categoryMatches")
|
|
}
|
|
|
|
export function hasExtendingTokensTypesMapProperty(
|
|
tokType: TokenType
|
|
): boolean {
|
|
return has(tokType, "categoryMatchesMap")
|
|
}
|
|
|
|
export function isTokenType(tokType: TokenType): boolean {
|
|
return has(tokType, "tokenTypeIdx")
|
|
}
|