Created
January 7, 2017 04:06
-
-
Save exts/a6a7f7a8b006a3a0d6ebac3fb8acdbe5 to your computer and use it in GitHub Desktop.
Crystal Lang: Screwing around, trying to figure out a simple way to parse a route w/ named parameters (and optional ones)
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
#idiotcoder.com | |
#eatcodegame.com | |
class RouteParser | |
@default_regex_replacement = "w+" | |
getter regex_variables = {} of String => String | |
getter default_variables = {} of String => String | |
getter matched_variables = [] of String | |
def initialize(@route = "") | |
extract_variables() | |
end | |
def regex(key : String, val : String) | |
if @matched_variables.includes?(key) | |
@regex_variables[key] = val | |
end | |
self | |
end | |
def default(key : String, val : String) | |
if @matched_variables.includes?(key) | |
@default_variables[key] = val | |
end | |
self | |
end | |
private def extract_variables | |
# reset array so we can't call this multiple times | |
@matched_variables = [] of String | |
# start the process | |
extract_variables(@route) | |
end | |
private def extract_variables(find : String) | |
if found = find.match /(?:\:([A-Za-z]+))/ | |
if !found[1]?.nil? | |
@matched_variables << found[1] if !@matched_variables.includes?(found[1]) | |
if !found.not_nil!.post_match.empty? | |
extract_variables(found.post_match) | |
end | |
end | |
end | |
end | |
def parse | |
# replace [] with (?:)? optional groups | |
route = @route.gsub("[", "(?:") | |
route = route.gsub("]", ")?") | |
route = route.gsub("/", "\\/") | |
@matched_variables.each do |mv| | |
rex = @regex_variables.fetch(mv, "\\" + @default_regex_replacement) | |
route = route.sub(":" + mv, "(?<" + mv + ">" + rex + ")") | |
end | |
route | |
end | |
end | |
str = "/post/:id[/:slug[/:other]]" | |
parser = RouteParser.new str | |
parser | |
.default("id", "1") | |
.default("slug", "") | |
.default("other", "") | |
.regex("id", %(\\d+)) | |
.regex("other", %([A-Za-z]+\\-\\d+)) | |
route = "/post/10/custm_slug/page-10" | |
if found = route.match /^#{parser.parse}$/ | |
puts found.not_nil!["id"]? # => 10 | |
puts found.not_nil!["slug"]? # => custom_slug | |
puts found.not_nil!["other"]? # => page-10 | |
end | |
puts parser.matched_variables # => ["id", "slug", "other"] | |
puts parser.default_variables # => {"id" => "1", "slug" => "", "other" => ""} | |
puts parser.regex_variables # => {"id" => "\\d+", "other" => "[A-Za-z]+\\-\\d+"} | |
puts parser.parse # => \/post\/(?<id>\d+)(?:\/(?<slug>\w+)(?:\/(?<other>[A-Za-z]+\-\d+))?)? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment