Skip to content

Commit

Permalink
Merge branch 'release/0.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
spat-ne-hochu committed Jun 19, 2016
2 parents 92b11f7 + 85f2009 commit f315041
Show file tree
Hide file tree
Showing 9 changed files with 381 additions and 21 deletions.
22 changes: 1 addition & 21 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,37 +1,17 @@
# Logs
logs
*.log
npm-debug.log*

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules
jspm_packages

# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history
.idea
18 changes: 18 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
sudo: false

cache:
directories:
- node_modules

language: node_js
node_js:
- "6"

before_script:
- "npm i -D"

script:
- "npm run coverage"

after_script:
- "cat ./coverage/lcov.info | coveralls"
53 changes: 53 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use strict';

var nodeParse = require('./lib/node-parse');

/**
*
* @param string
*
* @returns {CombineNode}
*/
module.exports = function(string) {
if (typeof string !== 'string') {
throw 'parse need string';
}

let state = new ParseState(string),
stack = [];

try {
do {
let node = nodeParse(state);

if (state.indent > 0) {
stack[state.indent - 1].addChild(node);
}

stack[state.indent] = node;
} while (! state.isEOF);
} catch (e) {
console.error(state, e);
throw 'parse error';
}

return stack[0];
};

class ParseState {
constructor(string) {
this.string = string;
this.lastBlockName = null;
this.index = 0;
this.line = 0;
this.isEOF = false;
}

execRegexp(regexp) {
regexp.lastIndex = this.index;
let result = regexp.exec(this.string);
this.index = regexp.lastIndex;

return result;
}
}
29 changes: 29 additions & 0 deletions lib/line-analyze.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use strict";

module.exports = function(state) {
var spaces = 0,
beforeIndex = state.index;

while (state.string[state.index] === ' ') {
spaces++;
state.index++;
}

var isNode;

if (spaces % 4 === 0) {
isNode = true;
} else if(spaces % 4 === 2) {
isNode = false;
} else {
throw 'invalid indent'
}

return {
beforeIndex: beforeIndex,
indent: Math.floor(spaces / 4),
isNode: isNode,
isProperty: ! isNode,
isEmpty: state.string[state.index] === '\n'
}
};
68 changes: 68 additions & 0 deletions lib/node-parse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const CombineNode = require('@combinejs/node'),
directiveProvider = require('@combinejs/directives-provider'),
lineAnalyze = require('./line-analyze');


module.exports = function(state) {
let {indent} = lineAnalyze(state);

let node = new CombineNode(nameParse(state));

if (node.isBlock) {
state.lastBlockName = node.blockName;
} else {
node.blockName = state.lastBlockName;
}

do {
let {isProperty, beforeIndex, indent: lineIndent} = lineAnalyze(state);

if (! isProperty) {
state.index = beforeIndex;
break;
}

if (lineIndent === indent) {
let {NS, name, value} = propertyParse(state);

if (NS === 'rule') {
let ConcreteDirective = directiveProvider(name);

node.addDirective(name, new ConcreteDirective(value, node));
} else {
node.setProp(NS, name, value);
}
}

} while (! state.isEOF);

state.indent = indent;

return node;
};

function nameParse(state) {
let result = state.execRegexp(/([a-z][a-z0-9]+)/gi);
LexemeEnding(state);

return result[1];
}

function propertyParse(state) {
let result = state.execRegexp(/([a-z][a-z0-9]+)\.([a-z][a-z0-9]+)\s*=\s*'([^']+)'/gi);
LexemeEnding(state);

return {
NS: result[1],
name: result[2],
value: result[3]
}
}

function LexemeEnding(state) {
let result = state.execRegexp(/\s*(\r?\n)+/mg);

if (result === null || state.index >= state.string.length - 1) {
state.isEOF = true;
}
}
38 changes: 38 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "@combinejs/parser",
"version": "0.1.0",
"description": "default combinejs parser",
"main": "index.js",
"scripts": {
"test": "mocha",
"coverage": "istanbul cover _mocha -- -R spec"
},
"repository": {
"type": "git",
"url": "git+https://github.com/combinejs/parser.git"
},
"author": "spat.ne.hochu",
"license": "ISC",
"bugs": {
"url": "https://github.com/combinejs/parser/issues"
},
"homepage": "https://github.com/combinejs/parser#readme",
"dependencies": {
"@combinejs/directives-provider": "^0.9.0",
"@combinejs/match-directive": "^0.1.0",
"@combinejs/node": "^0.1.1"
},
"devDependencies": {
"chai": "^3.5.0",
"coveralls": "^2.11.9",
"istanbul": "^0.4.3",
"mocha": "^2.5.3"
},
"files": [
"LICENSE",
"History.md",
"Readme.md",
"index.js",
"lib/"
]
}
24 changes: 24 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* global before, after, beforeEach, describe, it */

const assert = require('chai').assert,
fs = require('fs'),
path = require('path'),
parse = require('../index');


describe('parser tests', function() {
let block, json;

before('load test block', function() {
block = fs.readFileSync(path.resolve('./test/table-beauty.comb')).toString();
json = JSON.parse(fs.readFileSync(path.resolve('./test/table-beauty.json')));
});

it('parse table block', function() {
let tree = parse(block);

tree = JSON.parse(JSON.stringify(tree));

assert.deepEqual(tree, json);
});
});
22 changes: 22 additions & 0 deletions test/table-beauty.comb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
TableBeauty
html.tag = 'table'
css.display = 'table'

row
rule.match = '*'
html.tag = 'tr'
css.display = 'table-row'

cell
rule.match = '*'
html.tag = 'td'
css.display = 'table-cell'

head
rule.match = '1'
css.background = '#eee'
css.fontWeight = '900'

headCell
rule.match = '*'
html.tag = 'th'

0 comments on commit f315041

Please sign in to comment.