Created
November 14, 2016 01:51
-
-
Save liamwhite/01fbdb4f72c29f8ac5d18a0e7a1e2514 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Search | |
# Helper class for performing lexical analysis on a string. | |
class Lexer | |
attr_accessor :pos, :string | |
def initialize(string) | |
@string = string.dup | |
@pos = 0 | |
end | |
# The current substring to be analyzed. | |
def rest | |
@string[@pos .. -1] | |
end | |
# Are we at the end of this string? | |
def eos? | |
@pos == @string.length | |
end | |
# Move the scan pointer forward `count` characters, and return | |
# the string portion that was consumed. | |
def advance(count) | |
@pos += count | |
@string[@pos - count .. @pos - 1] | |
end | |
# Accept string and advance the scan pointer, or | |
# do nothing if no match. | |
def accept(str) | |
return unless rest.start_with?(str) | |
advance(str.length) | |
end | |
# Accept regex and advance the scan pointer, or | |
# do nothing if no match at begin. | |
def match(re) | |
return unless rest =~ /\A#{re}/ | |
advance($~.to_s.length) | |
end | |
# Accept until `re` matches and advance the scan pointer to the | |
# character before the match start, or consume the entire string | |
# if no match occurred. | |
def match_until(re) | |
current = rest | |
if current =~ re | |
advance($`.length) | |
else | |
@pos = @string.length | |
current | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment