Regular Expression in a Loop!

Fornoreason1000

Black Sheep
Veteran
Joined
Mar 1, 2014
Messages
206
Reaction score
95
First Language
English
Primarily Uses
RMMV
Just found and interesting but potentially brain scrambling bug involving using Regular expressions recursively. I consider it a potential trap for new players, (don't know what forum this fits into)
take this source string

<commandA: 10>
<commandA: 9>
<commandA: 5>
<commandA: 4>
<commandA: 3>

And the fucntion contain a For loop and a Regular expression.

Code:
   var commands = GetCommands(this.commandData); //gets string array
   var  regEXP = /<([^<>:]*):?[^>]*>/ig;
   
    for (var i = 0; i < commands.length; i++) {
     
        var line = commands[i].parameters[0];
        var match = regEXP.exec(line);
        console.log(match + "," + line);
        if (match && line) {
            this.parseCommand(match, line);
        }
    }
and the output is
[Object] <commandA: 10>
Null <commandA: 9>
[Object] <commandA: 8>
Null <commandA: 5>
[Object] <commandA: 4>
Null <commandA: 3>

As you can tell the strings should be matching but they are returning null?
Why? Well apparently Firefox and Apparently RPGmakers browser engine have this weird bug that cause the RegExp object to not update or something.

Another way to invoke this bug is to call exec on a Regular Expression Literal within the loop it self


Code:
    for (var i = 0; i < commands.length; i++) {
        var line = commands[i].parameters[0];
        var match = /<([^<>:]*):?[^>]*>/ig.exec(line);
        console.log(match + "," + line);
        if (match && line) {
            this.parseCommand(match, line);
        }
    }
this produces the same bug on firefox.
to work around this thing is to declare a variable within the for loop and Then call exec() on that,
Code:
for (var i = 0; i < commands.length; i++) {
     var regEXP = /<([^<>:]*):?[^>]*>/ig;
     var line = commands[i].parameters[0];
     var match = regEXP.exec(line);
     console.log(commands[i]+ "," + match + "," + line);
     if (match && line) {
         this.parseTournamentCommand(match, line);
     }
}
now the output is
[Object] <commandA: 10>
[Object] <commandA: 9>
[Object] <commandA: 8>
[Object] <commandA: 5>
[Object]<commandA: 4>
[Object] <commandA: 3>

Anyone else experience this or is it just me?
 

orzfly

Veteran
Veteran
Joined
Jan 11, 2016
Messages
18
Reaction score
79
First Language
Chinese
Primarily Uses
RMMV
Every instance of RegExp has a property named lastIndex. You should not reuse the instance if you are going to exec the RegExp on another string.

You can print regEXP.lastIndex and find the root reason:

<commandA: 10>,commandA,<commandA: 10>,14
null,<commandA: 9>,0
<commandA: 5>,commandA,<commandA: 5>,13
null,<commandA: 4>,0
<commandA: 3>,commandA,<commandA: 3>,13

You can learn more about it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec

If the match succeeds, the exec() method returns an array and updates properties of the regular expression object. The returned array has the matched text as the first item, and then one item for each capturing parenthesis that matched containing the text that was captured.
By the way, I don't believe that the second snippet would fail... Can you confirm it again?

1:
Code:
(function(){
   var commands = this.commandData; //gets string array
   var  regEXP = /<([^<>:]*):?[^>]*>/ig;
    for (var i = 0; i < commands.length; i++) {
        var line = commands[i].parameters[0];
        var match = regEXP.exec(line);
        console.log(match + "," + line);
    }
}).call({commandData:[{parameters:["<commandA: 10>"]},{parameters:["<commandA: 9>"]},{parameters:["<commandA: 5>"]},{parameters:["<commandA: 4>"]},{parameters:["<commandA: 3>"]}]})
<commandA: 10>,commandA,<commandA: 10>
null,<commandA: 9>
<commandA: 5>,commandA,<commandA: 5>
null,<commandA: 4>
<commandA: 3>,commandA,<commandA: 3>

2:
Code:
(function(){
   var commands = this.commandData; //gets string array
    for (var i = 0; i < commands.length; i++) {
        var line = commands[i].parameters[0];
        var match = /<([^<>:]*):?[^>]*>/ig.exec(line);
        console.log(match + "," + line);
    }
}).call({commandData:[{parameters:["<commandA: 10>"]},{parameters:["<commandA: 9>"]},{parameters:["<commandA: 5>"]},{parameters:["<commandA: 4>"]},{parameters:["<commandA: 3>"]}]})
<commandA: 10>,commandA,<commandA: 10>
<commandA: 9>,commandA,<commandA: 9>
<commandA: 5>,commandA,<commandA: 5>
<commandA: 4>,commandA,<commandA: 4>
<commandA: 3>,commandA,<commandA: 3>

3:
Code:
(function(){
   var commands = this.commandData; //gets string array

    for (var i = 0; i < commands.length; i++) {
        var regEXP = /<([^<>:]*):?[^>]*>/ig;
        var line = commands[i].parameters[0];
        var match = regEXP.exec(line);
        console.log(match + "," + line);
    }
}).call({commandData:[{parameters:["<commandA: 10>"]},{parameters:["<commandA: 9>"]},{parameters:["<commandA: 5>"]},{parameters:["<commandA: 4>"]},{parameters:["<commandA: 3>"]}]})
<commandA: 10>,commandA,<commandA: 10>
<commandA: 9>,commandA,<commandA: 9>
<commandA: 5>,commandA,<commandA: 5>
<commandA: 4>,commandA,<commandA: 4>
<commandA: 3>,commandA,<commandA: 3>
 

Fornoreason1000

Black Sheep
Veteran
Joined
Mar 1, 2014
Messages
206
Reaction score
95
First Language
English
Primarily Uses
RMMV
Yep your right... must of forgot to hit the save button on that second snippet.
Tried on Firefox, Edge and chrome and the second snippet works.

thanks for the link too
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Couple hours of work. Might use in my game as a secret find or something. Not sure. Fancy though no? :D
Holy stink, where have I been? Well, I started my temporary job this week. So less time to spend on game design... :(
Cartoonier cloud cover that better fits the art style, as well as (slightly) improved blending/fading... fading clouds when there are larger patterns is still somewhat abrupt for some reason.
Do you Find Tilesetting or Looking for Tilesets/Plugins more fun? Personally I like making my tileset for my Game (Cretaceous Park TM) xD
How many parameters is 'too many'??

Forum statistics

Threads
105,860
Messages
1,017,038
Members
137,568
Latest member
invidious
Top