lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Paul Ducklin once stated:
> Why try to convert the matching string into a regexp or Lua pattern at
> all? Sometimes regexp-type code is simply the wrong way to do things, but
> something we do merely from familiarity.
> 
> It sounds as though matching an input string X against the expression
> “/sport/#” in the fashion you describe is equivalent to:
> 
> X == “/sport” or X:sub(1,7) == “/sport/“
> 
> So why not just do it like that, and sidestep regexps, patterns,
> wildcards, state machines, and all that complexity? The code above is
> simpler, faster and self-documenting…

  That actually might be simpler.  Proof of concept:

local function match(pattern,target)
  -- --------------------------------------------
  -- I couldn't think of a better way to do this
  -- --------------------------------------------

  if pattern:match("#") and not pattern:match("#$") then
    error "bad pattern"
  end

  local pf,ps,pc = pattern:gmatch "[^/]*" -- capture values from iterator
  local tf,ts,tc = target:gmatch "[^/]*"
  
  while true do
    local pv = pf(ps,pc) -- get next segment in pattern
    local tv = tf(ts,tc) -- get next segment in target
    
    -- ---------------
    -- if we're at the end of the pattern, we should be at the end
    -- of the target
    -- ---------------
    
    if not pv then
      return not tv
    
    -- ----------------------------------------------------------------------
       If the patttern segment is '+', then the target is an automatic match
    -- ----------------------------------------------------------------------
    
    elseif pv == '+' then
      -- nothing to do here
      
    -- -----------------------------------------------------
    -- If the pattern is '#', then everything else matches
    -- -----------------------------------------------------
    
    elseif pv == '#' then
      return true
      
    -- ------------------------------------------------------
    -- compare the two segments, if unequal, result is false
    -- ------------------------------------------------------
    
    else
      if pv ~= tv then
        return false
      end
    end
  end
end

local function test(p,t)
  print(match(p,t),p,t)
end

test("sport/tennis/player1/#","sport/tennis/player1")
test("sport/tennis/player1/#","sport/tennis/player1/ranking")
test("sport/tennis/player1/#","sport/tennis/player1/score/wimbleton")

test("sport/tennis/+","sport/tennis/player1")
test("sport/tennis/+","sport/tennis/player2")
test("sport/tennis/+","sport/tennis/player1/ranking")

test("+/tennis/#","news/tennis")
test("+/tennis/#","news/tennis/mcenroe")
test("+/tennis/#","/tennis/mcenroe")
test("+/tennis/#","sports/tennis/williams")
test("+/tennis/#","sports/tennis/williams/ranking")
test("+/tennis/#","tennis")
test("+/tennis/#","game/fussbol")

test("+/+","/finance")
test("/+","/finance")

test("/sport/#","/sport")
test("/sport/#","/sport/racing")
test("/sport/#","/sport/racing/champion")
test("/sport/#","/sporting")

  -spc