Skip to content

Commit

Permalink
Showing 2 changed files with 86 additions and 42 deletions.
3 changes: 0 additions & 3 deletions spec/filters/bugs/strscan.rb
Original file line number Diff line number Diff line change
@@ -8,7 +8,6 @@
fails "StringScanner#[] raises a TypeError if the given index is nil"
fails "StringScanner#[] raises a TypeError when a Range is as argument"
fails "StringScanner#[] returns named capture"
fails "StringScanner#check_until returns the same value of scan_until, but don't advances the scan pointer"
fails "StringScanner#clear set the scan pointer to the end of the string and clear matching data."
fails "StringScanner#clear warns in verbose mode that the method is obsolete"
fails "StringScanner#concat concatenates the given argument to self and returns self"
@@ -72,8 +71,6 @@
fails "StringScanner#search_full returns the matched string if the third argument is true"
fails "StringScanner#search_full returns the number of bytes advanced and advances the scan pointer if the second argument is true"
fails "StringScanner#search_full returns the number of bytes advanced"
fails "StringScanner#skip_until returns nil if no match was found"
fails "StringScanner#skip_until returns the number of bytes advanced and advances the scan pointer until pattern is matched and consumed"
fails "StringScanner#string returns the string being scanned"
fails "StringScanner#string= changes the string being scanned to the argument and resets the scanner"
fails "StringScanner#string= converts the argument into a string using #to_str"
125 changes: 86 additions & 39 deletions stdlib/strscan.rb
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ def initialize(string)
@pos = 0
@matched = nil
@working = string
@match = []
@match = []
end

attr_reader :string
@@ -18,10 +18,11 @@ def beginning_of_line?

alias bol? beginning_of_line?

def scan(regex)
def scan(pattern)
pattern = anchor(pattern)

%x{
regex = new RegExp('^' + regex.toString().substring(1, regex.toString().length - 1));
var result = regex.exec(#@working);
var result = pattern.exec(#@working);
if (result == null) {
return #@matched = nil;
@@ -47,18 +48,18 @@ def scan(regex)
}
end

def scan_until(regex)
%x{
regex = new RegExp('^' + regex.toString().substring(1, regex.toString().length - 1));
def scan_until(pattern)
pattern = anchor(pattern)

%x{
var pos = #@pos,
working = #@working,
result;
while (true) {
result = regex.exec(working);
result = pattern.exec(working);
pos += 1;
working = working.substring(1);
working = working.substr(1);
if (result == null) {
if (working.length === 0) {
@@ -68,10 +69,10 @@ def scan_until(regex)
continue;
}
#@matched = #@string.substr(#@pos, pos - #@pos);
#@matched = #@string.substr(#@pos, pos - #@pos - 1 + result[0].length);
#@prev_pos = pos - 1;
#@pos = pos;
#@working = working;
#@working = working.substr(result[0].length);
return #@matched;
}
@@ -99,16 +100,36 @@ def [](idx)
}
end

def check(regex)
def check(pattern)
pattern = anchor(pattern)

%x{
var regexp = new RegExp('^' + regex.toString().substring(1, regex.toString().length - 1)),
result = regexp.exec(#@working);
var result = pattern.exec(#@working);
if (result == null) {
return #{self}.matched = nil;
return #@matched = nil;
}
return #@matched = result[0];
}
end

def check_until(pattern)
%x{
var prev_pos = #@prev_pos,
pos = #@pos;
var result = #{scan_until(pattern)};
if (result !== nil) {
#@matched = result.substr(-1);
#@working = #@string.substr(pos);
}
return #{self}.matched = result[0];
#@prev_pos = prev_pos;
#@pos = pos;
return result;
}
end

@@ -120,9 +141,9 @@ def eos?
`#@working.length === 0`
end

def exist?(regex)
def exist?(pattern)
%x{
var result = regex.exec(#@working);
var result = pattern.exec(#@working);
if (result == null) {
return nil;
@@ -136,37 +157,56 @@ def exist?(regex)
}
end

def skip(re)
def skip(pattern)
pattern = anchor(pattern)

%x{
re = new RegExp('^' + re.source)
var result = re.exec(#@working);
var result = pattern.exec(#@working);
if (result == null) {
return #{self}.matched = nil;
return #@matched = nil;
}
else {
var match_str = result[0];
var match_len = match_str.length;
#{self}.matched = match_str;
self.prev_pos = self.pos;
#{self}.pos += match_len;
#{self}.working = #{self}.working.substring(match_len);
#@matched = match_str;
#@prev_pos = #@pos;
#@pos += match_len;
#@working = #@working.substring(match_len);
return match_len;
}
}
end

def get_byte()
def skip_until(pattern)
%x{
var result = #{scan_until(pattern)};
if (result === nil) {
return nil;
}
else {
#@matched = result.substr(-1);
return result.length;
}
}
end

def get_byte
%x{
var result = nil;
if (#{self}.pos < #{self}.string.length) {
self.prev_pos = self.pos;
#{self}.pos += 1;
result = #{self}.matched = #{self}.working.substring(0, 1);
#{self}.working = #{self}.working.substring(1);
if (#@pos < #@string.length) {
#@prev_pos = #@pos;
#@pos += 1;
result = #@matched = #@working.substring(0, 1);
#@working = #@working.substring(1);
}
else {
#{self}.matched = nil;
#@matched = nil;
}
return result;
@@ -176,10 +216,11 @@ def get_byte()
# not exactly, but for now...
alias getch get_byte

def match?(regex)
def match?(pattern)
pattern = anchor(pattern)

%x{
regex = new RegExp('^' + regex.toString().substring(1, regex.toString().length - 1));
var result = regex.exec(#@working);
var result = pattern.exec(#@working);
if (result == null) {
return nil;
@@ -199,7 +240,7 @@ def pos=(pos)
}
}

@pos = pos
@pos = pos
@working = `#{@string}.slice(pos)`
end

@@ -247,9 +288,15 @@ def terminate
end

def unscan
@pos = @prev_pos
@pos = @prev_pos
@prev_pos = nil
@match = nil
@match = nil

self
end

private
def anchor(pattern)
`new RegExp('^' + pattern.toString().substr(1, pattern.toString().length - 2))`
end
end

0 comments on commit c604685

Please sign in to comment.