Navigation Menu

Skip to content

Commit

Permalink
Adding JSON to FBP support
Browse files Browse the repository at this point in the history
  • Loading branch information
aretecode committed Jul 3, 2016
1 parent d53b920 commit f339a54
Show file tree
Hide file tree
Showing 9 changed files with 536 additions and 5 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -2,6 +2,7 @@ language: node_js
sudo: false
node_js:
- '4.2'
- '6.2'
before_script:
- npm install -g grunt-cli
deploy:
Expand Down
3 changes: 3 additions & 0 deletions CHANGES.md
@@ -1,3 +1,6 @@
# fbp 1.5.0 - released 02.07.2016

* Add JSON to FBP parser

# fbp 1.4.0 - released 17.06.2016

Expand Down
13 changes: 11 additions & 2 deletions README.md
Expand Up @@ -26,7 +26,16 @@ When `caseSensitive` is `false` the parser will convert port names to lowercase.

The *fbp* package also provides a command-line tool for converting FBP files into JSON:

$ fbp somefile.fbp [--case-sensitive] > somefile.json
```
$ fbp somefile.fbp [--case-sensitive] > somefile.json
```

And for converting JSON files into FBP:

```
$ fbp somefile.json [--case-sensitive] > somefile.fbp
```


## Language for Flow-Based Programming

Expand All @@ -35,7 +44,7 @@ FBP is a Domain-Specific Language (DSL) for easy graph definition. The syntax is
* `'somedata' -> PORT Process(Component)` sends initial data _somedata_ to port _PORT_ of process _Process_ that runs component _Component_
* `A(Component1) X -> Y B(Component2)` sets up a connection between port _X_ of process _A_ that runs component _Component1_ and port _Y_ of process _B_ that runs component _Component2_

You can connect multiple components and ports together on one line, and separate connection definitions with a newline or a comma (`,`).
You can connect multiple components and ports together on one line, and separate connection definitions with a newline or a comma (`,`).

Components only have to be specified the first time you mention a new process. Afterwards, simply use the process name.

Expand Down
6 changes: 6 additions & 0 deletions bin/fbp
Expand Up @@ -20,5 +20,11 @@ if (!fs.existsSync(file)) {
process.exit(1);
}

fileType = file.split('.').pop()

if(fileType == 'json'){
return console.log(parser.parse(fs.readFileSync(file, 'utf-8')));
}

var result = parser.parse(fs.readFileSync(file, 'utf-8'), {caseSensitive: caseSensitive});
console.log(JSON.stringify(result, null, 2));
74 changes: 74 additions & 0 deletions lib/json.coffee
@@ -0,0 +1,74 @@
module.exports =
parse: (graph, options = {}) ->
input = JSON.parse graph
namedComponents = []
output = ""

getName = (name) ->
if input.processes[name].metadata?
name = input.processes[name].metadata.label

if name.indexOf('/') > -1
name = name.split('/').pop()
#name = name.replace('/', '_')

return name

getInOutName = (name, data) ->
if data.process? and input.processes[data.process].metadata?
name = input.processes[data.process].metadata.label

else if data.process?
name = data.process

if name.indexOf('/') > -1
name = name.split('/').pop()

return name

for name, inPort of input.inports
process = getInOutName name, inPort
name = name.toUpperCase()
inPort.port = inPort.port.toUpperCase()
output += "INPORT=#{process}.#{inPort.port}:#{name}\n"

for name, outPort of input.outports
process = getInOutName name, inPort
name = name.toUpperCase()
outPort.port = outPort.port.toUpperCase()
output += "OUTPORT=#{process}.#{outPort.port}:#{name}\n"

# add new lines after input and outports
output += "\n"

for conn in input.connections
# it is data added in the noflo graph (IP)
if conn.data?
tgtPort = conn.tgt.port.toUpperCase()
tgtName = conn.tgt.process
tgtProcess = input.processes[tgtName].component
tgt = getName tgtName
unless tgtProcess in namedComponents
tgt += "(#{tgtProcess})"
namedComponents.push tgtProcess
output += '"' + conn.data + '"' + " -> #{tgtPort} #{tgt}\n"
# is not data, is a connection
else
srcPort = conn.src.port.toUpperCase()
srcName = conn.src.process
srcProcess = input.processes[srcName].component
src = getName srcName
unless srcProcess in namedComponents
src += "(#{srcProcess})"
namedComponents.push srcProcess

tgtPort = conn.tgt.port.toUpperCase()
tgtName = conn.tgt.process
tgtProcess = input.processes[tgtName].component
tgt = getName tgtName
unless tgtProcess in namedComponents
tgt += "(#{tgtProcess})"
namedComponents.push tgtProcess
output += "#{src} #{srcPort} -> #{tgtPort} #{tgt}\n"

return output
84 changes: 84 additions & 0 deletions lib/json.js
@@ -0,0 +1,84 @@
var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

module.exports = {
parse: function(graph, options) {
var conn, getInOutName, getName, i, inPort, input, len, name, namedComponents, outPort, output, process, ref, ref1, ref2, src, srcName, srcPort, srcProcess, tgt, tgtName, tgtPort, tgtProcess;
if (options == null) {
options = {};
}
input = JSON.parse(graph);
namedComponents = [];
output = "";
getName = function(name) {
if (input.processes[name].metadata != null) {
name = input.processes[name].metadata.label;
}
if (name.indexOf('/') > -1) {
name = name.split('/').pop();
}
return name;
};
getInOutName = function(name, data) {
if ((data.process != null) && (input.processes[data.process].metadata != null)) {
name = input.processes[data.process].metadata.label;
} else if (data.process != null) {
name = data.process;
}
if (name.indexOf('/') > -1) {
name = name.split('/').pop();
}
return name;
};
ref = input.inports;
for (name in ref) {
inPort = ref[name];
process = getInOutName(name, inPort);
name = name.toUpperCase();
inPort.port = inPort.port.toUpperCase();
output += "INPORT=" + process + "." + inPort.port + ":" + name + "\n";
}
ref1 = input.outports;
for (name in ref1) {
outPort = ref1[name];
process = getInOutName(name, inPort);
name = name.toUpperCase();
outPort.port = outPort.port.toUpperCase();
output += "OUTPORT=" + process + "." + outPort.port + ":" + name + "\n";
}
output += "\n";
ref2 = input.connections;
for (i = 0, len = ref2.length; i < len; i++) {
conn = ref2[i];
if (conn.data != null) {
tgtPort = conn.tgt.port.toUpperCase();
tgtName = conn.tgt.process;
tgtProcess = input.processes[tgtName].component;
tgt = getName(tgtName);
if (indexOf.call(namedComponents, tgtProcess) < 0) {
tgt += "(" + tgtProcess + ")";
namedComponents.push(tgtProcess);
}
output += '"' + conn.data + '"' + (" -> " + tgtPort + " " + tgt + "\n");
} else {
srcPort = conn.src.port.toUpperCase();
srcName = conn.src.process;
srcProcess = input.processes[srcName].component;
src = getName(srcName);
if (indexOf.call(namedComponents, srcProcess) < 0) {
src += "(" + srcProcess + ")";
namedComponents.push(srcProcess);
}
tgtPort = conn.tgt.port.toUpperCase();
tgtName = conn.tgt.process;
tgtProcess = input.processes[tgtName].component;
tgt = getName(tgtName);
if (indexOf.call(namedComponents, tgtProcess) < 0) {
tgt += "(" + tgtProcess + ")";
namedComponents.push(tgtProcess);
}
output += src + " " + srcPort + " -> " + tgtPort + " " + tgt + "\n";
}
}
return output;
}
};
10 changes: 8 additions & 2 deletions package.json
@@ -1,11 +1,17 @@
{
"name": "fbp",
"description": "Parser for the .fbp flow definition language",
"version": "1.4.0",
"version": "1.5.0",
"repository": {
"type": "git",
"url": "git://github.com/flowbased/fbp.git"
},
"contributors": [
{
"name": "James",
"email": "aretecode@gmail.com"
}
],
"license": "MIT",
"devDependencies": {
"chai": "^3.5.0",
Expand All @@ -17,7 +23,7 @@
"grunt-noflo-browser": "^0.1.11",
"grunt-peg": "^2.0.1",
"grunt-yaml": "^0.4.2",
"mocha": "^2.4.4",
"mocha": "^2.5.3",
"tv4": "^1.2.7"
},
"keywords": [],
Expand Down
1 change: 0 additions & 1 deletion spec/fbp.coffee
Expand Up @@ -5,7 +5,6 @@ if typeof process isnt 'undefined' and process.execPath and process.execPath.ind
else
parser = require 'fbp'


describe 'FBP parser', ->
it 'should provide a parse method', ->
chai.expect(parser.parse).to.be.a 'function'
Expand Down

0 comments on commit f339a54

Please sign in to comment.