| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- /*jshint node:true */
- /*
- The MIT License (MIT)
- Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation files
- (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge,
- publish, distribute, sublicense, and/or sell copies of the Software,
- and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
- 'use strict';
- var regexp_has_sticky = RegExp.prototype.hasOwnProperty('sticky');
- function InputScanner(input_string) {
- this.__input = input_string || '';
- this.__input_length = this.__input.length;
- this.__position = 0;
- }
- InputScanner.prototype.restart = function() {
- this.__position = 0;
- };
- InputScanner.prototype.back = function() {
- if (this.__position > 0) {
- this.__position -= 1;
- }
- };
- InputScanner.prototype.hasNext = function() {
- return this.__position < this.__input_length;
- };
- InputScanner.prototype.next = function() {
- var val = null;
- if (this.hasNext()) {
- val = this.__input.charAt(this.__position);
- this.__position += 1;
- }
- return val;
- };
- InputScanner.prototype.peek = function(index) {
- var val = null;
- index = index || 0;
- index += this.__position;
- if (index >= 0 && index < this.__input_length) {
- val = this.__input.charAt(index);
- }
- return val;
- };
- // This is a JavaScript only helper function (not in python)
- // Javascript doesn't have a match method
- // and not all implementation support "sticky" flag.
- // If they do not support sticky then both this.match() and this.test() method
- // must get the match and check the index of the match.
- // If sticky is supported and set, this method will use it.
- // Otherwise it will check that global is set, and fall back to the slower method.
- InputScanner.prototype.__match = function(pattern, index) {
- pattern.lastIndex = index;
- var pattern_match = pattern.exec(this.__input);
- if (pattern_match && !(regexp_has_sticky && pattern.sticky)) {
- if (pattern_match.index !== index) {
- pattern_match = null;
- }
- }
- return pattern_match;
- };
- InputScanner.prototype.test = function(pattern, index) {
- index = index || 0;
- index += this.__position;
- if (index >= 0 && index < this.__input_length) {
- return !!this.__match(pattern, index);
- } else {
- return false;
- }
- };
- InputScanner.prototype.testChar = function(pattern, index) {
- // test one character regex match
- var val = this.peek(index);
- pattern.lastIndex = 0;
- return val !== null && pattern.test(val);
- };
- InputScanner.prototype.match = function(pattern) {
- var pattern_match = this.__match(pattern, this.__position);
- if (pattern_match) {
- this.__position += pattern_match[0].length;
- } else {
- pattern_match = null;
- }
- return pattern_match;
- };
- InputScanner.prototype.read = function(starting_pattern, until_pattern, until_after) {
- var val = '';
- var match;
- if (starting_pattern) {
- match = this.match(starting_pattern);
- if (match) {
- val += match[0];
- }
- }
- if (until_pattern && (match || !starting_pattern)) {
- val += this.readUntil(until_pattern, until_after);
- }
- return val;
- };
- InputScanner.prototype.readUntil = function(pattern, until_after) {
- var val = '';
- var match_index = this.__position;
- pattern.lastIndex = this.__position;
- var pattern_match = pattern.exec(this.__input);
- if (pattern_match) {
- match_index = pattern_match.index;
- if (until_after) {
- match_index += pattern_match[0].length;
- }
- } else {
- match_index = this.__input_length;
- }
- val = this.__input.substring(this.__position, match_index);
- this.__position = match_index;
- return val;
- };
- InputScanner.prototype.readUntilAfter = function(pattern) {
- return this.readUntil(pattern, true);
- };
- InputScanner.prototype.get_regexp = function(pattern, match_from) {
- var result = null;
- var flags = 'g';
- if (match_from && regexp_has_sticky) {
- flags = 'y';
- }
- // strings are converted to regexp
- if (typeof pattern === "string" && pattern !== '') {
- // result = new RegExp(pattern.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), flags);
- result = new RegExp(pattern, flags);
- } else if (pattern) {
- result = new RegExp(pattern.source, flags);
- }
- return result;
- };
- InputScanner.prototype.get_literal_regexp = function(literal_string) {
- return RegExp(literal_string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
- };
- /* css beautifier legacy helpers */
- InputScanner.prototype.peekUntilAfter = function(pattern) {
- var start = this.__position;
- var val = this.readUntilAfter(pattern);
- this.__position = start;
- return val;
- };
- InputScanner.prototype.lookBack = function(testVal) {
- var start = this.__position - 1;
- return start >= testVal.length && this.__input.substring(start - testVal.length, start)
- .toLowerCase() === testVal;
- };
- module.exports.InputScanner = InputScanner;
|