From 6fed91d728c25e357fa4435af3f87b70da619f15 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Wed, 26 Dec 2012 17:48:01 -0500 Subject: [PATCH] Update chunker, fixes #184. --- lib/carto/parser.js | 79 ++++++++++----------- test/rendering/weird_simple_comments.mml | 14 ++++ test/rendering/weird_simple_comments.mss | 1 + test/rendering/weird_simple_comments.result | 23 ++++++ 4 files changed, 77 insertions(+), 40 deletions(-) create mode 100644 test/rendering/weird_simple_comments.mml create mode 100644 test/rendering/weird_simple_comments.mss create mode 100644 test/rendering/weird_simple_comments.result diff --git a/lib/carto/parser.js b/lib/carto/parser.js index f5f160d..2a00069 100644 --- a/lib/carto/parser.js +++ b/lib/carto/parser.js @@ -197,17 +197,19 @@ carto.Parser = function Parser(env) { } var early_exit = false; + // Split the input into chunks. - chunks = (function(chunks) { + chunks = (function (chunks) { var j = 0, - skip = /[^"'`\{\}\/]+/g, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, level = 0, match, chunk = chunks[0], - inString; + inParam; - chunker: for (var i = 0, c, cc; i < input.length; i++) { + for (var i = 0, c, cc; i < input.length;) { skip.lastIndex = i; if (match = skip.exec(input)) { if (match.index === i) { @@ -216,58 +218,55 @@ carto.Parser = function Parser(env) { } } c = input.charAt(i); - comment.lastIndex = i; + comment.lastIndex = string.lastIndex = i; - if (!inString && c === '/') { + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { cc = input.charAt(i + 1); if (cc === '/' || cc === '*') { - match = comment.exec(input); - if (match) { + if (match = comment.exec(input)) { if (match.index === i) { - i += match[0].length - 1; + i += match[0].length; chunk.push(match[0]); - c = input.charAt(i); - continue chunker; + continue; } } } } - if (c === '{' && !inString) { level++; - chunk.push(c); - } else if (c === '}' && !inString) { level--; - chunk.push(c); - chunks[++j] = chunk = []; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break; } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break; } + case '(': if (! inParam) { inParam = true; chunk.push(c); break; } + case ')': if ( inParam) { inParam = false; chunk.push(c); break; } + default: chunk.push(c); } + + i++; } - if (level > 0) { - if (inString) { - // TODO: make invalid instead - throw makeError({ - message: 'Missing closing ' + inString, - index: i - }); - } else { - // TODO: make invalid instead - throw makeError({ - message: 'Missing closing `}`', - index: i - }); - } + if (level !== 0) { + error = new LessError({ + index: i - 1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.filename + }, env); } - return chunks.map(function(c) { return c.join(''); }); + return chunks.map(function (c) { return c.join(''); }); })([[]]); + if (error) { + throw makeError(error); + } + // Start with the primary rule. // The whole syntax tree is held under a Ruleset node, // with the `root` property set to true, so no `{}` are diff --git a/test/rendering/weird_simple_comments.mml b/test/rendering/weird_simple_comments.mml new file mode 100644 index 0000000..6c26b3e --- /dev/null +++ b/test/rendering/weird_simple_comments.mml @@ -0,0 +1,14 @@ +{ + "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", + "Stylesheet": [ + "weird_simple_comments.mss" + ], + "Layer": [{ + "name": "world", + "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", + "Datasource": { + "file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip", + "type": "shape" + } + }] +} diff --git a/test/rendering/weird_simple_comments.mss b/test/rendering/weird_simple_comments.mss new file mode 100644 index 0000000..c28c8ea --- /dev/null +++ b/test/rendering/weird_simple_comments.mss @@ -0,0 +1 @@ +#world { one/marker-file: url(http://upload.wikimedia.org/wikipedia/commons/7/72/Cup_of_coffee.svg); two/marker-file: url('http://upload.wikimedia.org/wikipedia/commons/7/72/Cup_of_coffee.svg'); three/marker-file: url(http://upload.wikimedia.org/wikipedia/en/c/ce/SVG-logo.svg); four/marker-file: url("http://a.tiles.mapbox.com/v3/marker/pin-m-fast-food+AA0000.png"); } diff --git a/test/rendering/weird_simple_comments.result b/test/rendering/weird_simple_comments.result new file mode 100644 index 0000000..886a2fd --- /dev/null +++ b/test/rendering/weird_simple_comments.result @@ -0,0 +1,23 @@ + + + + + + + + world + + + + + + +