Page 1 of 1

Help with string pattern matching

Posted: Mon Mar 14, 2022 6:01 pm
by Kavaline
Hi, I can't find the string pattern solution to make my code works on all situations:

Code: Select all

--main.lua
function love.load(args)
	local lib = require "lib"
	local act = lib.connect()

	--act:read("action item to entity")
	act:read("sell apple to alpha")
	act:read("sell red_potion to alpha")

	print()
	act:read("sell apple, steel to alpha")
	act:read("sell apple , steel to alpha")
	act:read("sell apple ,steel to alpha")
	act:read("sell apple,steel to alpha")

	print()
	act:read("sell red_potion, steel to alpha")
	act:read("sell red_potion , steel to alpha")
	act:read("sell red_potion ,steel to alpha")
	act:read("sell red_potion,steel to alpha")

	print()
	act:read("sell apple, red_potion to alpha")
	act:read("sell apple , red_potion to alpha")
	act:read("sell apple ,red_potion to alpha")
	act:read("sell apple,red_potion to alpha")

	print()
	act:read("sell @ to alpha")
end

function love.update(dt)
end

function love.draw(dt)
end

Code: Select all

--lib.lua
local L = {}
local action = {}

local MT = {
  __index = action
}

function L.connect()
	local obj = { a = 1 }
	return setmetatable(obj, MT)
end

function action.read(self, params)
	local f = params
	local command = f:match("^(%S*)")
	f = string.sub(f, string.len(command)+2)
	print(command, f)
	if command == "sell" then
		local col = {}
		while f:match("(%S*)") ~= "to" do
			col[#col+1] = f:match("(%S*)[%s,*]")
			--col[#col+1] = f:match("(%w*)[%s,*]")
			--col[#col+1] = f:match("([%w%s]*)[%s,*]")
			f = string.sub(f, string.len(col[#col])+2)
			print("item added")
		end
		for k,v in ipairs(col) do print(k, v) end
	elseif command == "buy" then
	end
end

L.action = action

return L
I want the results like "apple", "red_potion", "steel" in all situations, but I can't find the right pattern to fit it. Someone can help?
(also, this is a minimalist code with my logic problem for a library, so, another way to deal with this isn't an option, i need a string pattern)

Re: Help with string pattern matching

Posted: Mon Mar 14, 2022 9:36 pm
by MrFariator
This pattern seemed to handle all of the listed test cases in your post, if the intention is indeed to stop at "to". If you were to expand this, you could make a lookup table for words that are supposed to break the loop. Not tested for performance, since I wrote it in like few minutes.

Code: Select all

-- the actual pattern
local pattern = "([a-zA-Z0-9_]+)"

-- string to test against
local str = "sell red_potion, steel"

-- parse the string
while true do
  local sub = str:match(pattern)
  if sub == "to" then
    break
  end
  str = string.sub ( str, string.find(str, sub) + string.len(sub) + 1 )
  
  print ( sub )

  -- precaution
  if string.len (str) == 0 then
    break
  end
end

Re: Help with string pattern matching

Posted: Tue Mar 15, 2022 12:25 am
by pgimeno
It's not too clear what you're after, but I think this has a chance of doing what you want.

By the way, what is @ supposed to mean?

Code: Select all

function action.read(self, params)
	local command = params:match("^%s*(%S+)")
	print("Command: " .. command)
	if command == "sell" then
		local col = {}
		local items, dest = params:match("^%s*%S+%s+(.-)%s+to%s+(.-)%s*$")
		if not items then error("Wrong sell line") end
		print("Selling to " .. dest .. ".")
		for item in items:gmatch("[^,]+") do
			itemname = item:match("^%s*(.-)%s*$")
			col[#col + 1] = itemname
			print("Added item: " .. itemname .. ".")
		end
		for k,v in ipairs(col) do print(k, v) end
	elseif command == "buy" then
	end
end

Re: Help with string pattern matching

Posted: Tue Mar 15, 2022 2:16 am
by Kavaline
Well, @ is just @, is a special symbol (and the only symbol), it will trigger an event.
Also, I found another solution, but your solution looks better, and your approach makes me thinks on an easy way for next time, separating the items instead of looking the ending indicator... And MrFariator's idea is great too, I wil expand this code to deal with others situations with different scope.

Code: Select all

function action.read(self, params)
	local f = params
	local command = f:match("^(%S*)")
	f = string.sub(f, string.len(command)+2)
	print(command, f)
	if command == "sell" then
		local col = {}
		while f:match("%s?(%S*)") ~= "to" do
			col[#col+1] = f:match("([%w_%@]+)[%s,*]")
			f = string.sub(f, string.len(col[#col]) + 1 + f:find("[%@%w]"))
			print("item added", col[#col], f)
		end
		for k,v in ipairs(col) do print(k, v) end
	elseif command == "buy" then
	end
end
Thanks so much guys!