Skip to content

Instantly share code, notes, and snippets.

@liamwhite
Created November 14, 2016 01:51
Show Gist options
  • Save liamwhite/01fbdb4f72c29f8ac5d18a0e7a1e2514 to your computer and use it in GitHub Desktop.
Save liamwhite/01fbdb4f72c29f8ac5d18a0e7a1e2514 to your computer and use it in GitHub Desktop.
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