diff --git a/lib/jison.js b/lib/jison.js index 7333362ef..e21351e3b 100755 --- a/lib/jison.js +++ b/lib/jison.js @@ -1173,17 +1173,33 @@ lrGeneratorMixin.generateTableCode = function (table) { // Don't surround numerical property name numbers in quotes moduleCode = moduleCode.replace(/"([0-9]+)"(?=:)/g, "$1"); - // Replace objects with identical values for all keys by function calls - // e.g., { 1: [6,7]; 3: [6,7], 4: [6,7] } = o([6,7], [1, 3, 4]) - moduleCode = moduleCode.replace(/\{\d+:(\[[^\]]+\]),\d+:\1[^\}]*\}/g, function (object, value) { - // Check if all values in this object are identical, and collect its keys - var keyValue, keys = [], keyValueMatcher = /(\d+):([^:]+)(?=,\d+:|\})/g; - while (keyValue = keyValueMatcher.exec(object)) - // Only continue if the keys are identical - if (value !== keyValue[2]) return object; - else keys.push(keyValue[1]) - // Create a function call with the value and all keys - return 'o(' + value + ',[' + keys.join(',') + '])'; + // Replace objects with several identical values by function calls + // e.g., { 1: [6, 7]; 3: [6, 7], 4: [6, 7], 5: 8 } = o([1, 3, 4], [6, 7], { 5: 8 }) + moduleCode = moduleCode.replace(/\{\d+:[^\}]+,\d+:[^\}]+\}/g, function (object) { + // Find the value that occurs with the highest number of keys + var value, frequentValue, key, keys = {}, keyCount, maxKeyCount = 0, + keyValue, keyValues = [], keyValueMatcher = /(\d+):([^:]+)(?=,\d+:|\})/g; + while ((keyValue = keyValueMatcher.exec(object))) { + // For each value, store the keys where that value occurs + key = keyValue[1], value = keyValue[2], keyCount = 1; + if (!(value in keys)) keys[value] = [key]; + else keyCount = keys[value].push(key); + // Remember this value if it is the most frequent one + if (keyCount > maxKeyCount) + maxKeyCount = keyCount, frequentValue = value; + } + // Construct the object with a function call if the most frequent value occurs multiple times + if (maxKeyCount > 1) { + // Collect all non-frequent values into a remainder object + for (value in keys) + if (value !== frequentValue) + for (k = keys[value], i = 0, l = k.length; i < l; i++) + keyValues.push(k[i] + ':' + value); + keyValues = keyValues.length ? ',{' + keyValues.join(',') + '}' : ''; + // Create the function call `o(keys, value, remainder)` + object = 'o([' + keys[frequentValue].join(',') + '],' + frequentValue + keyValues + ')'; + } + return object; }); // Count occurrences of number lists @@ -1214,11 +1230,11 @@ lrGeneratorMixin.generateTableCode = function (table) { moduleCode: moduleCode }; }; -// Function that creates an object with the given value for all given keys -// e.g., o([6,7], [1, 3, 4]) = { 1: [6,7]; 3: [6,7], 4: [6,7] } -var createObjectCode = 'o=function(v,a,l,r){' + - 'for(l=a.length,r={};l--;r[a[l]]=v);' + - 'return r}'; +// Function that extends an object with the given value for all given keys +// e.g., o([1, 3, 4], [6, 7], { x: 1, y: 2 }) = { 1: [6, 7]; 3: [6, 7], 4: [6, 7], x: 1, y: 2 } +var createObjectCode = 'o=function(k,v,o,l){' + + 'for(o=o||{},l=k.length;l--;o[k[l]]=v);' + + 'return o}'; // Creates a variable with a unique name function createVariable() {