Skip to content

Instantly share code, notes, and snippets.

@ishiduca
Created July 9, 2017 09:41
Show Gist options
  • Save ishiduca/ca24c809a40e1bcd5737d4e8d433bccd to your computer and use it in GitHub Desktop.
Save ishiduca/ca24c809a40e1bcd5737d4e8d433bccd to your computer and use it in GitHub Desktop.
チェーン・コマンドパース
var inherits = require('inherits')
var Parser = require('../parser').Parser
module.exports = DoneParser
inherits(DoneParser, Parser)
function DoneParser () {
Parser.call(this)
}
DoneParser.prototype._parse = function (str) {
return new Promise(resolve => {
if (str.toUpperCase() === '!DONE') resolve({method: 'getDone'})
else resolve(false)
})
}
var inherits = require('inherits')
var Parser = require('../parser').Parser
module.exports = FavsParser
inherits(FavsParser, Parser)
function FavsParser () {
Parser.call(this)
}
FavsParser.prototype._parse = function (str) {
return new Promise((resolve, reject) => {
if (str.toUpperCase().slice(0, 5) !== '!FAVS') return resolve(false)
var match = str.toUpperCase().match(/^!FAVS(?:\s+([1-5]))?$/)
if (match) {
if (match[1]) {
resolve({method: 'getFavs', value: Number(match[1])})
} else {
resolve({method: 'getFavs', value: 0})
}
} else {
reject(new Error('FavsParserError - "' + str + '"'))
}
})
}
{
"dependencies": {
"inherits": "^2.0.3",
"yo-yo": "^1.4.1"
},
"devDependencies": {
"tap-spec": "^4.1.1",
"tape": "^4.7.0"
},
"scripts": {
"test": "NODE_PATH=src tape t/*.js | tap-spec",
"build": "browserify src/main.js -o bundle.js"
}
}
function Parser () {
this.parser = null
}
Parser.prototype.parse = function parse (str, cb) {
if (typeof str !== 'string') return cb(new TypeError('command must be "string"'))
str = str.split(' ').filter(Boolean).join(' ')
if (!str) return cb(new Error('command not found'))
var me = this
this._parse(str).then(match => {
if (match) return cb(null, match)
if (me.parser == null) {
cb(new Error('parser can not parse "' + str + '"'))
} else {
me.parser.parse(str, cb)
}
}).catch(err => cb(err))
}
Parser.prototype._parse = function _pase (str) {
throw new Error('need to implement "._parse"')
}
module.exports = setup
module.exports.Parser = Parser
function setup () {
var args = [].slice.apply(arguments)
var F = args.shift()
var f = new F()
args.reduce(function (f, Parser) {
f.parser = new Parser()
return f.parser
}, f)
return f
}
'use strict'
var test = require('tape')
var setup = require('parser')
var DoneParser = require('parsers/done')
var FavsParser = require('parsers/favs')
test('parser.parse(str, (err, command) => {...}', t => {
var parser = setup(
DoneParser,
FavsParser
)
t.test('case "!done"', tt => {
parser.parse('!done', (err, c) => {
tt.notOk(err, 'no exists error')
tt.deepEqual(c, {method: 'getDone'})
tt.end()
})
})
t.test('case "!dones"', tt => {
parser.parse('!dones', (err, c) => {
tt.notOk(c, 'no exists command')
tt.ok(/^parser can not parse "!dones"$/.test(err.message))
tt.end()
})
})
t.test('case "!favs"', tt => {
parser.parse('!favs', (err, c) => {
tt.notOk(err, 'no exists error')
tt.deepEqual(c, {method: 'getFavs', value: 0})
tt.end()
})
})
t.test('case "!favs 5"', tt => {
parser.parse('!favs 5', (err, c) => {
tt.notOk(err, 'no exists error')
tt.deepEqual(c, {method: 'getFavs', value: 5})
tt.end()
})
})
t.test('case "!favs 6"', tt => {
parser.parse('!favs 6', (err, c) => {
tt.notOk(c, 'no exists command')
tt.ok(/^FavsParserError - "!favs 6"$/.test(err.message))
tt.end()
t.end()
})
})
})
@ishiduca
Copy link
Author

ishiduca commented Jul 9, 2017

実際の場面では、コールバックで受けた結果をobserverなどを通して、それぞれのAPIに処理を委譲する

var onParsed = (err, command) => {
  if (err) emitter.emit('error', err)
  else emitter.emit(command.method, command.value)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment