whitespaceArrayNewline = array_merge($whitespaceArray, ["\n"]); // placeholders are unused code points; see also https://en.wikipedia.org/wiki/Private_Use_Areas $e->whitespaceArrayPlaceholders = ["\x{E000}", "\x{E001}", "\x{E002}"]; $whitespaceChars = implode("", $whitespaceArray); $e->whitespaceCharsNewline = "\n" . $whitespaceChars; $whitespace = "[" . $whitespaceChars . "]"; $whitespaceNewline = "[" . $e->whitespaceCharsNewline . "]"; // possessive quantifier (++) is needed when used in combination with look ahead $e->someWhitespace = $whitespace . "++"; $someWhitespaceNewline = $whitespaceNewline . "++"; $optionalWhitespace = $whitespace . "*+"; $e->optionalWhitespaceNewline = $whitespaceNewline . "*+"; // a single escaped character in a regexp, like \\ or \n (may not be newline) $regexEscape = "\\\\[^\n]"; // regexp character class: [..] with escape characters // [^\n\\]] is any non-] character (also not be newline) $characterClass = "\\[(?:" . $regexEscape . "|[^\n\\]])*+\\]"; // regexp: /..(..)../i with character class and escaped characters // [^\n/] is any non-slash character (also not be newline) $e->regexp = "/(?:" . $regexEscape . "|" . $characterClass . "|[^\n/])++/[igmus]*+"; // characters than can form a word; these characters should not be joined together by the removal of whitespace $word = "[a-zA-Z0-9_\$\x{0080}-\x{FFFF}]"; // note: ! is not infix and not safe $safeOperators = ",\.&|*/%=<>?:"; $openingBrackets = "({["; $closingBrackets = ")}\\]"; $expressionClosingBracket = ")"; $blockOpeningBracket = "{"; // newlines that may be safely removed $e->safeNewlines = [ // newline preceded by opening bracket or operator "(?<=[;" . $openingBrackets . $safeOperators . "])" . "\n", // newline followed by closing bracket or operator "\n" . "(?=[;" . $closingBrackets. $safeOperators . "])", // ( \n [ "(?<=[" . $openingBrackets . "])" . "\n" . "(?=[" . $openingBrackets . "])", // ] \n ) "(?<=[" . $closingBrackets . "])" . "\n" . "(?=[" . $closingBrackets . "])", // } \n ( "(?<=[" . $expressionClosingBracket . "])" . "\n" . "(?=[" . $blockOpeningBracket . "])", ]; // these expression must always be present, because they keep tokens that contain whitespace together $e->tokenExpressions = [ // /** comment */ 'starComment' => "(?" . "/\*.*?\*/" . $e->optionalWhitespaceNewline . ")", // // comment 'lineComment' => "(?//[^\n]*" . $e->optionalWhitespaceNewline . ")", // regular expression 'regexp' => "(?" . // if there's whitespace, match it all $e->regexp . $optionalWhitespace . // to distinguish a regexp from a sequence of dividers (i.e.: x / y / z): "(?:" . // it is followed by a newline; add it to the match "\n" . "|" . // it is followed by any of these characters "(?=[;,\.)])" . ")" . ")", // "double quotes" 'double' => '(?"(?:\\\\.|[^"])*+")', // 'single quotes' 'single' => "(?'(?:\\\\.|[^'])*+')", // `template literal` 'template' => "(?`(?:\\\\.|[^`])*+`)", ]; $specificExpressions = [ // a sequence of - and -- operators; i.e. a - --b; b-- -c; d-- - -e; f - -g 'min' => "(?<=-)(?" . $someWhitespaceNewline . ")(?=-)", // a sequence of + and ++ operators 'plus' => "(?<=\+)(?" . $someWhitespaceNewline . ")(?=\+)", // whitespace both preceded and succeeded by a word char 'requiredSpace' => "(?<=" . $word . ")" . "(?" . $someWhitespaceNewline . ")" . "(?=" . $word . ")" ]; $e->allExpressions = array_merge($e->tokenExpressions, $specificExpressions); return $e; } }