Help with string pattern matching

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Kavaline
Prole
Posts: 8
Joined: Sun Jun 27, 2021 5:19 pm

Help with string pattern matching

Post 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)
MrFariator
Party member
Posts: 563
Joined: Wed Oct 05, 2016 11:53 am

Re: Help with string pattern matching

Post 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
User avatar
pgimeno
Party member
Posts: 3689
Joined: Sun Oct 18, 2015 2:58 pm

Re: Help with string pattern matching

Post 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
Kavaline
Prole
Posts: 8
Joined: Sun Jun 27, 2021 5:19 pm

Re: Help with string pattern matching

Post 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!
Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests