UNPKG

monaco-editor-core

Version:

A browser based code editor

144 lines (143 loc) 4.37 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ export function isFuzzyActionArr(what) { return (Array.isArray(what)); } export function isFuzzyAction(what) { return !isFuzzyActionArr(what); } export function isString(what) { return (typeof what === 'string'); } export function isIAction(what) { return !isString(what); } // Small helper functions /** * Is a string null, undefined, or empty? */ export function empty(s) { return (s ? false : true); } /** * Puts a string to lower case if 'ignoreCase' is set. */ export function fixCase(lexer, str) { return (lexer.ignoreCase && str ? str.toLowerCase() : str); } /** * Ensures there are no bad characters in a CSS token class. */ export function sanitize(s) { return s.replace(/[&<>'"_]/g, '-'); // used on all output token CSS classes } // Logging /** * Logs a message. */ export function log(lexer, msg) { console.log(`${lexer.languageId}: ${msg}`); } // Throwing errors export function createError(lexer, msg) { return new Error(`${lexer.languageId}: ${msg}`); } // Helper functions for rule finding and substitution /** * substituteMatches is used on lexer strings and can substitutes predefined patterns: * $$ => $ * $# => id * $n => matched entry n * @attr => contents of lexer[attr] * * See documentation for more info */ export function substituteMatches(lexer, str, id, matches, state) { const re = /\$((\$)|(#)|(\d\d?)|[sS](\d\d?)|@(\w+))/g; let stateMatches = null; return str.replace(re, function (full, sub, dollar, hash, n, s, attr, ofs, total) { if (!empty(dollar)) { return '$'; // $$ } if (!empty(hash)) { return fixCase(lexer, id); // default $# } if (!empty(n) && n < matches.length) { return fixCase(lexer, matches[n]); // $n } if (!empty(attr) && lexer && typeof (lexer[attr]) === 'string') { return lexer[attr]; //@attribute } if (stateMatches === null) { // split state on demand stateMatches = state.split('.'); stateMatches.unshift(state); } if (!empty(s) && s < stateMatches.length) { return fixCase(lexer, stateMatches[s]); //$Sn } return ''; }); } /** * substituteMatchesRe is used on lexer regex rules and can substitutes predefined patterns: * $Sn => n'th part of state * */ export function substituteMatchesRe(lexer, str, state) { const re = /\$[sS](\d\d?)/g; let stateMatches = null; return str.replace(re, function (full, s) { if (stateMatches === null) { // split state on demand stateMatches = state.split('.'); stateMatches.unshift(state); } if (!empty(s) && s < stateMatches.length) { return fixCase(lexer, stateMatches[s]); //$Sn } return ''; }); } /** * Find the tokenizer rules for a specific state (i.e. next action) */ export function findRules(lexer, inState) { let state = inState; while (state && state.length > 0) { const rules = lexer.tokenizer[state]; if (rules) { return rules; } const idx = state.lastIndexOf('.'); if (idx < 0) { state = null; // no further parent } else { state = state.substr(0, idx); } } return null; } /** * Is a certain state defined? In contrast to 'findRules' this works on a ILexerMin. * This is used during compilation where we may know the defined states * but not yet whether the corresponding rules are correct. */ export function stateExists(lexer, inState) { let state = inState; while (state && state.length > 0) { const exist = lexer.stateNames[state]; if (exist) { return true; } const idx = state.lastIndexOf('.'); if (idx < 0) { state = null; // no further parent } else { state = state.substr(0, idx); } } return false; }