| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- /*---------------------------------------------------------------------------------------------
- * 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 '';
- });
- }
- /**
- * 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;
- }
|