Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern fixes #30

Open
wants to merge 3 commits into
base: pattern-fixes
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions test/scripts/control-structures.lua
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,10 @@ for key, val in pairs(u) do
a = a..'['..tostring(key)..'=='..tostring(val)..']'
end


assertTrue (string.find(a, '[6.28==tau]') ~= nil, 'for/pairs iteration should include items with double as key.')
assertTrue (string.find(a, '[@!#==qbert]') ~= nil, 'for/pairs iteration should include items with string as key.')
assertTrue (string.find(a, '[table: 0x%d+==1729]') ~= nil, 'for/pairs iteration should include items with table as key.')
assertTrue (string.find(a, '[function: 0x%d+==test]') ~= nil, 'for/pairs iteration should include items with function as key.')
assertTrue (string.find(a, '6.28==tau') ~= nil, 'for/pairs iteration should include items with double as key.')
assertTrue (string.find(a, '@!#==qbert') ~= nil, 'for/pairs iteration should include items with string as key.')
assertTrue (string.find(a, 'table: 0x%d+==1729') ~= nil, 'for/pairs iteration should include items with table as key.')
assertTrue (string.find(a, 'function: 0x%d+==test') ~= nil, 'for/pairs iteration should include items with function as key.')



5 changes: 4 additions & 1 deletion test/scripts/lib-string.lua
Original file line number Diff line number Diff line change
Expand Up @@ -545,10 +545,13 @@ assertTrue(l == nil, 'string.match() should handle nested char-sets correctly [2

local a = string.match('[123x456]','[0%x]')
local b = string.match('123x456','[0%D]')
local c = string.match('123x456','[0%Dfg%p2]')
local d = string.match('123x456','[0%Dfg%p5]')

assertTrue(a == '1', 'string.match() should return the correct values from character classes in char-sets [1]')
assertTrue(b == 'x', 'string.match() should return the correct values from character classes in char-sets [2]')

assertTrue(c == '2', 'string.match() should return the first match from character classes in char-sets [1]')
assertTrue(d == 'x', 'string.match() should return the first match from character classes in char-sets [2]')



Expand Down
151 changes: 148 additions & 3 deletions vm/src/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
'%c': '[\x00-\x1f]',
'%C': '[^\x00-\x1f]',
'%d': '\\d',
'%D': '[^\d]',
'%D': '[^\\d]',
'%l': '[a-z]',
'%L': '[^a-z]',
'%p': '[\.\,\"\'\?\!\;\:\#\$\%\&\(\)\*\+\-\/\<\>\=\@\[\]\\\^\_\{\}\|\~]',
Expand Down Expand Up @@ -146,19 +146,149 @@
return ('0' + (Math.floor((dayOfYear - offset) / 7) + 1)).substr(-2);
}

function groupToAlternativeGroupMatch(pattern) {
// Translates from [0%Dafd%xwombat] to ([0] | %D | [afd] | %x | [wombat])
var l = pattern.length;
var alternativeMatch = '(';
var i, character;

for (i = 1; i < (l-1); i++) {
character = pattern.substr(i, 1);

var characterToEscape = pattern.substr(i+1,1);
var charactersToExpand = "aAcCdDlLpPsSuUwWxX";

if (character == '%' && charactersToExpand.indexOf(characterToEscape) > -1) {
if (i != 1) {
alternativeMatch += "]|";
}

alternativeMatch += pattern.substr(i,2);
i += 1;

if (i+1 < (l-1)) {
alternativeMatch += "|[";
} else {
alternativeMatch += ')';
return alternativeMatch;
}
} else {
if (i == 1) {
alternativeMatch += '[';
}
alternativeMatch += character;
}
}
alternativeMatch += '])';
return alternativeMatch;
}

function translatePattern (pattern) {
// TODO Add support for balanced character matching (not sure this is easily achieveable).
pattern = '' + pattern;
console.log('Initial Pattern:',pattern);

var n = 0, l, character;
l = pattern.length;

for (i = 0; i < l; i++) {
character = pattern.substr(i, 1);

if (character == '%') {
// Skip the next character since we've escaped this one.
if (i < l) { i++; }
} else if (character == '[' ) {

// We've started the set, we need to end the set.
var startCharacter = i;
var foundEscape = false;

// Get the first character in the set.
i++; character = pattern.substr(i,1);
// The carat immediately allows us to use the next character as the unskippable one.
if (character == '^') {
i++; character = pattern.substr(i,1);
}

do {
if (i == l) {
// Throw an error.
}
if (character == '%') {
if (i < l) { i++; }
character = pattern.substr(i,1);
var charactersToExpand = "aAcCdDlLpPsSuUwWxX";
if (charactersToExpand.indexOf(character) > -1) {
foundEscape = true;
}
}
if (i < l) { i++; }
character = pattern.substr(i,1);
} while (character != ']');

if (foundEscape == true) {
l = pattern.length
var groupPatternLength = i-startCharacter;
var altPattern = groupToAlternativeGroupMatch(pattern.substr(startCharacter, groupPatternLength+1));
console.log('Pattern Before Concatenation:',pattern);
pattern = pattern.substr(1,startCharacter-1) + altPattern + pattern.substr(i, l-i-1);
console.log('Pattern After Concatenation:',pattern);
i = startCharacter + altPattern.length + 1; character = pattern.substr(i,1);
}
}

}

console.log('Pattern (step 1) :',pattern);

for (var i in ROSETTA_STONE) {
if (ROSETTA_STONE.hasOwnProperty(i)) {
pattern = pattern.replace(new RegExp(i, 'g'), ROSETTA_STONE[i]);
}
}

console.log('Pattern (step 2) :',pattern);
l = pattern.length;

for (i = 0; i < l; i++) {
character = pattern.substr(i, 1);

if (character == '\\') {
// Skip the next character since we've escaped this one.
if (i < l) { i++; }
} else if (character == '[' ) {

// We've started the set, we need to end the set.

// Get the first character in the set.
i++; character = pattern.substr(i,1);
// The carat immediately allows us to use the next character as the unskippable one.
if (character == '^') {
i++; character = pattern.substr(i,1);
}
// Check if the first character is a ]. If it is, it's special
// (as far as Lua is concerned) and needs to be escaped.
if (character == ']') {
pattern = pattern.substr(0, i) + '\\' + pattern.substr(i++);
l++;
}

do {
if (i == l) {
// Throw an error.
}
if (character == '\\') {
if (i < l) { i++; }
}
if (i < l) { i++; }
character = pattern.substr(i,1);
} while (character != ']');

}

}

console.log('Resulting Pattern:',pattern);
return pattern;
}

Expand Down Expand Up @@ -1862,10 +1992,25 @@

var matches = s.match(new RegExp(translatePattern (pattern)));

if (!matches) return;
if (!matches[1]) return matches[0];
console.log('matches:', matches);

if (!matches) {
console.log('match returns nil');
return;
}

console.log('matches[0]:', matches[0]);

if (!matches[1]) {
console.log('match returns:',matches[0]);
return matches[0];
}

console.log('matches[1]:', matches[1]);

matches.shift();

console.log('match returns:',matches);
return matches;
},

Expand Down