FG Spreadshirt Swag

Thread: LUA "Regex"

  1. #1

    LUA "Regex"

    So I know LUA doesn't use a "complete" regular expression feature but I am wondering how people handle something like this.

    Code:
    local sLevel, sSpells = sText:match("(first|second|third|fourth|fifth|sixth|seventh) (['’,%w%d%s%-%(%)]+)");
    In regex that would match the string first or second or third/etc... and capture both into sLevel and sSpells.

    Unfortunately that doesn't work in LUA.

    Code:
    local sDice,_, sSign,sMod = sDiceText:match((%d+[Dd]%d+)(([%-+])(%d+))?)
    This would match "1d6+2" and if no modifier just "1d6". This "(something)?" doesn't seem to be possible in LUA either. You can use single character tests with ? like "[%.$]?" and it'll work but trying to do it for a captured "(string)?" doesn't.

    How do you guys work around these limitations?

    For the last case I think this might be a good way.

    Code:
    local sDice = sDiceText:match(%d+[Dd]%d+[%-+]+%d+)  or sDice:match(%d+[Dd]%d+)
    And then I'd further split it up to get the number, size, sign and modifiers.

    Am I just missing some obvious way to do this sorta thing or is it really just adding a lot more checks to do what I'm trying to get the solution? The (check|check2|check3) really bites me at times
    ---
    Fantasy Grounds AD&D Reference Bundle, AD&D Adventure Bundle 1, AD&D Adventure Bundle 2
    Documentation for AD&D 2E ruleset.
    Custom Maps (I2, S4, T1-4, Barrowmaze,Lost City of Barakus)
    Note: Please do not message me directly on this site, post in the forums or ping me in FG's discord.

  2. #2
    I might not be interpreting your question correctly but:
    local sDice,sDie,sSign,sMod = string.match(sDiceText, "(%d+)%s*[Dd]+%s*(%d+)%s*([-%+]*)%s*(%d*)")
    (For example, " 13 D 100 - 17 " returns 13, 100, -, 17. "1d6+2" returns 1, 6, +, 2. "1d6" returns 1, 6, empty, empty)
    Last edited by gamerhawaii; January 18th, 2019 at 02:48.

  3. #3
    Quote Originally Posted by gamerhawaii View Post
    I might not be interpreting your question correctly but:
    local sDice,sDie,sSign,sMod = string.match(sDiceText, "(%d+)%s*[Dd]+%s*(%d+)%s*([-%+]*)%s*(%d*)")
    (For example, " 13 D 100 - 17 " returns 13, 100, -, 17. "1d6+2" returns 1, 6, +, 2. "1d6" returns 1, 6, empty, empty)
    I suppose I picked a bad example... although your conclusion still stands. I can't think of an example where this wouldn't work. I can add more checks of the vars and figure out what is actually there. I'll need to test gmatch for this tho because I think I ran into problems with that one.

    You don't happen to know of a way around the (check1|check2|...) do ya?
    ---
    Fantasy Grounds AD&D Reference Bundle, AD&D Adventure Bundle 1, AD&D Adventure Bundle 2
    Documentation for AD&D 2E ruleset.
    Custom Maps (I2, S4, T1-4, Barrowmaze,Lost City of Barakus)
    Note: Please do not message me directly on this site, post in the forums or ping me in FG's discord.

  4. #4
    Sorry, I do not know an easy way for something like (check1|check2|...) in Lua in FG.

    But check out "manager_string.lua" in the CORE ruleset. It seems to have functions that you might be able to use to do what you need (or least use them as a starting point in creating your own utility function to do it.) It also has some functions for dice expressions.

    However, in your first example, one guess is to just capture the first word as the spell level and then the rest as the spell text. (You did not show an exact example of what you are trying to parse, so I am just guessing for a solution for that particular case.)
    Last edited by gamerhawaii; January 18th, 2019 at 05:07.

  5. #5
    So my testing has found that it doesn't work right.

    This won't match "2 slams (1d10)".

    Code:
    for sCount,sDChar,sSize,sSign,sMod in string.gmatch(sDamageRaw,"(%d+)([dD%-])(%d+)([%+%-])(%d+)") do
    ...
    end
    If I change it to "2 slams (1d10+1)" it will. I understand why it will not match previous but if I could do something like "(%d+)([dD%-])(%d+)([%+%-])?(%d+)?" it would.
    ---
    Fantasy Grounds AD&D Reference Bundle, AD&D Adventure Bundle 1, AD&D Adventure Bundle 2
    Documentation for AD&D 2E ruleset.
    Custom Maps (I2, S4, T1-4, Barrowmaze,Lost City of Barakus)
    Note: Please do not message me directly on this site, post in the forums or ping me in FG's discord.

  6. #6
    This won't match "2 slams (1d10)".
    Ok, so what is that supposed to give and is that the whole text of the line? That is, is "2 slams (1d10)" in the middle of the line or the whole text. And what do you want back?

    I say this because if I use the exact expression I wrote above it gives me back sDice=1 and sDie=10. That is what I assumed you wanted. In your example, you changed the expression from what I had. For example, you removed the "*" after the "[-%+]" which means that a + or - is going to be required, not optional. Also, you made the modifier not optional by changing the "*" to a "+". Also, gmatch and match do not work the same. I used match. What I wrote does not work if using gmatch.

    Try this:
    for sCount,sDChar,sSize,sSign,sMod in string.gmatch(sDamageRaw,"(%d+)([dD])(%d+)([%+-]*)(%d*)") do

    sDamageRaw = "blah blah blah 2 slams (1d10) blah blah blah" gives 1, d, 10, empty, empty for the five variables
    Last edited by gamerhawaii; January 18th, 2019 at 05:43.

  7. #7
    I've had to work around it by using word parsing; and then comparing the parsed words. That's what I did in a lot of the auto-parsing code in 3.5E, 4E and 5E. Look for StringManager.parseWords and StringManager.isWord as well as a few other functions used throughout those rulesets.

    Regards,
    JPG

  8. #8
    Yes, StringManager is the "manager_string.lua" file. I should have mentioned that. Thanks for the clarification and the additional insight.

  9. #9
    Quote Originally Posted by gamerhawaii View Post
    "(%d+)([dD])(%d+)([%+-]*)(%d*)"
    You know I missed the bit where you used * where I used +. I wasn't aware it worked like that for [blah]* or %w*. I'll test that and see if I have better luck. Thanks for the tip!
    ---
    Fantasy Grounds AD&D Reference Bundle, AD&D Adventure Bundle 1, AD&D Adventure Bundle 2
    Documentation for AD&D 2E ruleset.
    Custom Maps (I2, S4, T1-4, Barrowmaze,Lost City of Barakus)
    Note: Please do not message me directly on this site, post in the forums or ping me in FG's discord.

  10. #10
    This is what I ended up with that works. It flips through the string, finds a match then removes it from the raw string, adds it to the attacks table and then checks for another and runs through the process till all dice strings are found.

    Code:
          for sCount,sDChar,sSize,sSign,sMod in string.gmatch(sDamageRaw,"(%d+)([dD%-])(%d+)([%+%-]?)(%d*)") do
            if (sCount ~= nil) and sSize ~= nil and sSign ~= nil and sMod ~= nil then
              local sDice = sCount .. sDChar .. sSize .. sSign .. sMod;
              sDamageRaw = string.gsub(sDamageRaw,sDice,"",1);      
              table.insert(aAttacks, sDice);
            elseif (sCount ~= nil and sSize ~= nil) then
              local sDice = sCount .. sDChar .. sSize;
              sDamageRaw = string.gsub(sDamageRaw,sDice,"",1);      
              table.insert(aAttacks, sDice);
            end
          end
    For my other "or" issue where I use (this match|or this match|or this match) I've worked out this. It will capture the 2 different styles of stat block entries for spells memorized (if they exist). It's a bit more work but does function.

    Code:
    local sSpellFilter = "['’,%w%d%s%-%(%)]+";
    local aLevelsAsName = { "first","second","third","fourth","fifth","sixth","seventh","eighth","ninth"};
    
      -- 'spells memorized: first level: command, cure light wounds (x2), remove fear, sanctuary second level: hold person (x2), resist fire, silence 15' radius, slow poison third level: dispel magic, prayer, bestow curse fourth level: cure serious wounds'
      -- or 
      -- 'spells memorized: level 1: detect magic, magic missile (x2), unseen servant level 2: detect invisibility, invisibility, web level 3: dispel magic, haste, lightning bolt level 4: charm monster, polymorph self level 5: teleport '
      for i=1,9,1 do
        spells[i] = sTextLower:match(aLevelsAsName[i] .. " level: (".. sSpellFilter .. ") %w+ level:") 
                 or sTextLower:match(aLevelsAsName[i] .. " level: (".. sSpellFilter .. ")")
                 or sTextLower:match("level " .. i .. ": (".. sSpellFilter .. ") level %d+:")
                 or sTextLower:match("level " .. i .. ": (".. sSpellFilter .. ")");
      end
    ---
    Fantasy Grounds AD&D Reference Bundle, AD&D Adventure Bundle 1, AD&D Adventure Bundle 2
    Documentation for AD&D 2E ruleset.
    Custom Maps (I2, S4, T1-4, Barrowmaze,Lost City of Barakus)
    Note: Please do not message me directly on this site, post in the forums or ping me in FG's discord.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
DICE PACKS BUNDLE

Log in

Log in