aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/nodejs/parse.js155
-rw-r--r--src/nodejs/tests/pathparsing.js8
-rw-r--r--src/nodejs/tests/urlToResObj.js63
3 files changed, 186 insertions, 40 deletions
diff --git a/src/nodejs/parse.js b/src/nodejs/parse.js
index 0338954..321823b 100644
--- a/src/nodejs/parse.js
+++ b/src/nodejs/parse.js
@@ -1,48 +1,131 @@
-exports.urlToXpathObj = function urlToXpathObj(url){
- // FIXMEresult.shift(): more validaiton
- // filter stars in keys
- // filter no enough arguments
- var parseKeyList = function(string){
- result = /(.+)(:?\|(.+))/.exec(string);
- result.shift();
- return result;
- }
+var parser = function(){
- var parseBboxList = function(string){
+ var offset =0;
+ var expr ="";
- result = /(.+)(:?,(.+)){3}/.exec(string);
+ var keys = [];
+ var values = [];
+ var bbox= {};
+ var object = "";
- if(result.length != 4){
- throw "error";
- }
+ var check = function(char){
+ if (expr.charAt(offset) != char) {
+ throw "Unexpected char " + expr[offset] + " at " + offset + " expected: " + char;
+ }
+ offset ++;
+ }
+
+ var parsePredicate = function(){
+ check('[');
+ parseInnerPredicate();
+ check(']');
+ }
- result.shift();
+ var parseInnerPredicate = function(){
+ tmpKeys=[];
+ parseKeyValue(tmpKeys,'=');
+ check('=');
+ if(tmpKeys.length==1 && tmpKeys[0] == "bbox"){
+ parseBboxValues();
+ } else {
+ keys = tmpKeys;
+ parseKeyValue(values,']');
+ }
+ }
- return {
- 'left' : result[0],
- 'bottom' : result[1],
- 'right' : result[2],
- 'top' : result[3]
- }
- }
-
- var xp = {};
+ var parseBboxValues = function(){
+ bbox.left = parseBboxFloat();
+ check(',');
+ bbox.bottom = parseBboxFloat();
+ check(',');
+ bbox.right = parseBboxFloat();
+ check(',');
+ bbox.top = parseBboxFloat();
+ }
- result = /\/(*|node|way|relation)(:?\[(.*)=(.*)\])*/.exec(url);
+ var parseBboxFloat = function(){
+ var floatStr = "";
+ while(expr[offset]!=',' && expr[offset]!=']' && offset < expr.length){
+ floatStr += expr[offset];
+ offset ++;
+ }
+ return parseFloat(floatStr);
+ }
- xp.object=result[1];
+ var parseKeyValue = function(list,delim){
+ var word = "";
+ while(expr[offset]!=delim && offset < expr.length){
+ if(expr[offset]=='|'){
+ list.push(word);
+ word="";
+ offset ++;
+ continue;
+ }
+ // jump escaped chars
+ if(expr[offset]=='\\'){
+ word += expr[offset];
+ offset ++;
+ }
+ word += expr[offset];
+ offset ++;
+ }
+ list.push(word);
- for(i=2;i<=result.length;i++){
- if(result[i]==="bbox"){
- xp.bbox = parseBboxValues(result[i+1]);
- } else {
- xp.tag ={};
- xp.tag.keys = parseKeyList(result[i]);
- xp.tag.values = parseKeyList(result[i+1]);
- }
- i++;
- }
+ }
+
+ this.parse = function(exprLocal){
+ expr = exprLocal;
+ offset = 0;
+ object = "";
+
+
+
+ check('/');
+
+ for(;expr[offset]!='[' && offset<expr.length;offset++){
+ if(expr[offset] == '/' && offset == expr.length-1){
+ offset ++;
+ break;
+ }
+ object += expr[offset];
+ }
+
+ if (object != "*" && object != "way" && object != "node" && object != "relation"){
+ throw "invalid identifier: " + object;
+ }
+
+
+ for(var i=0; i<3 && offset < expr.length;i++) {
+ parsePredicate();
+ }
+ if (offset < expr.length){
+
+ throw "string longer than excepected";
+ }
+
+ var result = {
+ object : object
+ };
+
+ if(bbox.left != undefined){
+ result.bbox = bbox;
+ }
+
+ if(keys.length > 0){
+
+ result.tag = {
+ key : keys,
+ value : values
+ }
+ }
+ return result;
+ }
}
+
+exports.urlToXpathObj = function urlToXpathObj(url){
+ var parse = new parser();
+ return parse.parse(url);
+}
diff --git a/src/nodejs/tests/pathparsing.js b/src/nodejs/tests/pathparsing.js
index e1a20f5..ebd5baf 100644
--- a/src/nodejs/tests/pathparsing.js
+++ b/src/nodejs/tests/pathparsing.js
@@ -54,7 +54,7 @@ module.exports =
test.ok(true);
var simpleRelationStringTrail = "/relation/";
var expected = { object: "relation" };
- assert.deepEqual(toTest(simpleRelationStringTrail), expectedi);
+ assert.deepEqual(toTest(simpleRelationStringTrail), expected);
test.finish();
}
@@ -78,20 +78,20 @@ module.exports =
, 'tag with two values': function(test) {
test.ok(true);
var nodeWithTwoValues = "/node[tag=foo|bar]";
- var expected = { object: "node", tag: { key:["key"], value:["foo", "bar"]}};
+ var expected = { object: "node", tag: { key:["tag"], value:["foo", "bar"]}};
assert.deepEqual(toTest(nodeWithTwoValues), expected);
test.finish();
}
, 'tag with two keys': function(test) {
test.ok(true);
- var nodeWithTwoKeys = "/node[foo,bar=value]";
+ var nodeWithTwoKeys = "/node[foo|bar=value]";
var expected = { object: "node", tag: { key:["foo", "bar"], value:["value"]}};
assert.deepEqual(toTest(nodeWithTwoKeys), expected);
test.finish();
}
, 'tags with cross product': function(test) {
test.ok(true);
- var tagCrossProduct = "/node[key1,key2=value1,value2]";
+ var tagCrossProduct = "/node[key1|key2=value1|value2]";
var expected = { object: "node", tag: {key:["key1", "key2"], value:["value1", "value2"]}};
assert.deepEqual(toTest(tagCrossProduct), expected);
test.finish();
diff --git a/src/nodejs/tests/urlToResObj.js b/src/nodejs/tests/urlToResObj.js
new file mode 100644
index 0000000..b45edfd
--- /dev/null
+++ b/src/nodejs/tests/urlToResObj.js
@@ -0,0 +1,63 @@
+var assert = require('assert');
+var test = require('../parse.js');
+
+
+//TODO function does not exist yet
+var toTest = test.urlToXpathObj;
+
+
+// test all simple objects { node, way, relation }
+
+var simpleNodeString = "/node";
+var expected = { object: "node" };
+assert.deepEqual(toTest(simpleNodeString), expected);
+
+var simpleNodeStringTrail = "/node/";
+var expected = { object: "node" };
+assert.deepEqual(toTest(simpleNodeStringTrail), expected);
+
+var simpleWayString = "/way";
+var expected = { object: "way" };
+assert.deepEqual(toTest(simpleWayString), expected);
+
+var simpleWayStringTrail = "/way/";
+var expected = { object: "way" };
+assert.deepEqual(toTest(simpleWayStringTrail), expected);
+
+var simpleRelationString = "/relation";
+var expected = { object: "relation" };
+assert.deepEqual(toTest(simpleRelationString), expected);
+
+var simpleRelationStringTrail = "/relation/";
+var expected = { object: "relation" };
+assert.deepEqual(toTest(simpleRelationStringTrail), expected);
+
+// TODO invalid object eg not (node, way, relation)
+
+var nodeWithBbox = "/node[bbox=0,51.5,0.25,51.75]";
+var expected = { object: "node", bbox: {left:0, bottom:51.5, right:0.25, top:51.75} };
+assert.deepEqual(toTest(nodeWithBbox), expected);
+
+var nodeWithSimpleTag = "/node[key=value]";
+var expected = { object: "node", tag: { key:["key"], value:["value"]}};
+assert.deepEqual(toTest(nodeWithSimpleTag), expected);
+
+var nodeWithTwoValues = "/node[tag=foo|bar]";
+var expected = { object: "node", tag: { key:["key"], value:["foo", "bar"]}};
+assert.deepEqual(toTest(nodeWithTwoValues), expected);
+
+var nodeWithTwoKeys = "/node[foo,bar=value]";
+var expected = { object: "node", tag: { key:["foo", "bar"], value:["value"]}};
+assert.deepEqual(toTest(nodeWithTwoKeys), expected);
+
+var tagCrossProduct = "/node[key1,key2=value1,value2]";
+var expected = { object: "node", tag: {key:["key1", "key2"], value:["value1", "value2"]}};
+assert.deepEqual(toTest(tagCrossProduct), expected);
+
+var nodeBboxTag = "/node[bbox=0,0,0,0][key=value]";
+var nodeTagBbox = "/node[bbox=0,0,0,0][key=value]";
+var expected = { object: "node", bbox: {left:0,bottom:0,right:0,top:0}, tag: {key:["key"], value:["value"]}};
+assert.deepEqual(toTest(nodeBboxTag), expected);
+assert.deepEqual(toTest(nodeTagBbox), expected);
+
+