Last active
December 15, 2015 21:39
-
-
Save gerardpaapu/5327480 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Parser = function() { | |
"use strict"; | |
function require(name) { | |
if (!(name in modules)) { | |
throw new Error("Module not found: " + name); | |
} | |
return modules[name]; | |
} | |
var modules = {}; | |
(function(exports) { | |
var Location, Port; | |
Port = function() { | |
function Port(source, _index) { | |
this.source = source; | |
this._index = _index != null ? _index : 0; | |
} | |
Port.from = function(str) { | |
if (str instanceof Port) { | |
return str; | |
} else { | |
return new Port(str); | |
} | |
}; | |
Port.prototype.take = function(n) { | |
return this.slice(0, n); | |
}; | |
Port.prototype.drop = function(n) { | |
return this.move(n); | |
}; | |
Port.prototype.isEmpty = function() { | |
return this.source.length <= this._index; | |
}; | |
Port.prototype.move = function(n) { | |
return new Port(this.source, this._index + n); | |
}; | |
Port.prototype.index = function(n) { | |
if (n < 0) { | |
return n; | |
} else { | |
return this._index + n; | |
} | |
}; | |
Port.prototype.slice = function(a, b) { | |
switch (arguments.length) { | |
case 0: | |
return this.source.slice(this.index(0)); | |
case 1: | |
return this.source.slice(this.index(a)); | |
default: | |
return this.source.slice(this.index(a), this.index(b)); | |
} | |
}; | |
Port.prototype.getLocation = function() { | |
var column, i, row; | |
row = 0; | |
column = 0; | |
i = 0; | |
while (i < this._index) { | |
if (this.source.charAt(i++) === "\n") { | |
column = 0; | |
row++; | |
} else { | |
column++; | |
} | |
} | |
return new Location(row, column); | |
}; | |
Port.prototype.toString = function() { | |
return this.slice(0); | |
}; | |
return Port; | |
}(); | |
exports.Port = Port; | |
Location = function() { | |
function Location(row, column) { | |
this.row = row; | |
this.column = column; | |
} | |
return Location; | |
}(); | |
exports.Location = Location; | |
}).call(null, modules["./Port"] = {}); | |
(function(exports) { | |
var typeString; | |
typeString = function(obj) { | |
var full; | |
if (obj != null) { | |
full = Object.prototype.toString.call(obj); | |
return full.slice(8, -1); | |
} else { | |
return String(obj); | |
} | |
}; | |
exports.addMethods = function(Klass) { | |
var converters; | |
converters = {}; | |
Klass.addConverter = function(type, fn) { | |
if (converters[type] != null) { | |
throw new Error("" + type + " is already defined"); | |
} | |
return converters[type] = fn; | |
}; | |
return Klass.from = function(obj) { | |
var instance, type; | |
type = typeString(obj); | |
if (obj instanceof Klass) { | |
return obj; | |
} else if (typeof converters[type] === "function") { | |
instance = converters[type](obj); | |
if (!(instance instanceof Klass)) { | |
throw new TypeError("converted value is not a instance of " + Klass); | |
} | |
return instance; | |
} else { | |
throw new TypeError("No converter from " + type + " is defined"); | |
} | |
}; | |
}; | |
}).call(null, modules["./From"] = {}); | |
(function(exports) { | |
var Failure, Result, Success, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { | |
function ctor() { | |
this.constructor = child; | |
} | |
for (var key in parent) { | |
if (__hasProp.call(parent, key)) child[key] = parent[key]; | |
} | |
ctor.prototype = parent.prototype; | |
child.prototype = new ctor; | |
child.__super__ = parent.prototype; | |
return child; | |
}; | |
Result = function() { | |
function Result() {} | |
Result.succeedWithValue = function(value) { | |
return new Success(value); | |
}; | |
Result.failWithMessage = function(message) { | |
return new Failure(message); | |
}; | |
Result.bind = function(m, f) { | |
return m.bind(f); | |
}; | |
Result.mzero = function() { | |
return Result.failWithMessage("failed"); | |
}; | |
Result.mreturn = function(value) { | |
return Result.succeedWithValue(value); | |
}; | |
return Result; | |
}(); | |
Success = function(_super) { | |
function Success(value) { | |
this.value = value; | |
} | |
__extends(Success, _super); | |
Success.prototype.didSucceed = true; | |
Success.prototype.bind = function(fn) { | |
return fn(this.value); | |
}; | |
return Success; | |
}(Result); | |
Failure = function(_super) { | |
function Failure(message) { | |
this.message = message; | |
} | |
__extends(Failure, _super); | |
Failure.prototype.didSucceed = false; | |
Failure.prototype.bind = function(_) { | |
return this; | |
}; | |
return Failure; | |
}(Result); | |
exports.Result = Result; | |
exports.Success = Success; | |
exports.Failure = Failure; | |
}).call(null, modules["./Result"] = {}); | |
(function(exports) { | |
var Continuation, Failure, Message, Parser, Port, Result, Success, _ref, _ref1, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { | |
function ctor() { | |
this.constructor = child; | |
} | |
for (var key in parent) { | |
if (__hasProp.call(parent, key)) child[key] = parent[key]; | |
} | |
ctor.prototype = parent.prototype; | |
child.prototype = new ctor; | |
child.__super__ = parent.prototype; | |
return child; | |
}; | |
_ref = require("./Result"), Result = _ref.Result, Success = _ref.Success, Failure = _ref.Failure; | |
Parser = function() { | |
function Parser(parse) { | |
this.parse = parse; | |
} | |
Parser.prototype.parse = function(source) { | |
throw new Error("Not Implemented"); | |
}; | |
return Parser; | |
}(); | |
Continuation = function() { | |
function Continuation(value, source) { | |
this.value = value; | |
this.source = source; | |
} | |
return Continuation; | |
}(); | |
Message = function() { | |
function Message(text, source) { | |
this.text = text; | |
this.source = source; | |
} | |
return Message; | |
}(); | |
_ref1 = require("./Result"), Result = _ref1.Result, Success = _ref1.Success, Failure = _ref1.Failure; | |
Parser.Succeed = function(_super) { | |
function Succeed(value) { | |
this.value = value; | |
} | |
__extends(Succeed, _super); | |
Succeed.prototype.parse = function(source) { | |
var continuation; | |
continuation = new Continuation(this.value, source); | |
return new Success(continuation); | |
}; | |
return Succeed; | |
}(Parser); | |
Parser.Fail = function(_super) { | |
function Fail(text) { | |
this.text = text; | |
} | |
__extends(Fail, _super); | |
Fail.prototype.parse = function(source) { | |
var message; | |
message = new Message(this.text, source); | |
return new Failure(message); | |
}; | |
return Fail; | |
}(Parser); | |
Port = require("./Port").Port; | |
Parser.Item = function(_super) { | |
function Item() {} | |
__extends(Item, _super); | |
Item.prototype.parse = function(source) { | |
var continuation, rest, val; | |
source = Port.from(source); | |
if (source.isEmpty()) { | |
return new Failure("Source empty", source); | |
} else { | |
val = source.take(1); | |
rest = source.drop(1); | |
continuation = new Continuation(val, rest); | |
return new Success(continuation); | |
} | |
}; | |
return Item; | |
}(Parser); | |
Message = function() { | |
function Message(text, source) { | |
this.text = text; | |
this.source = source; | |
} | |
return Message; | |
}(); | |
Continuation = function() { | |
function Continuation(value, source) { | |
this.value = value; | |
this.source = source; | |
} | |
return Continuation; | |
}(); | |
Parser.mzero = function() { | |
return new Parser.Fail("zero"); | |
}; | |
Parser.mreturn = function(v) { | |
return new Parser.Succeed(v); | |
}; | |
Parser.bind = function(m, f) { | |
var _this = this; | |
return new Parser(function(source) { | |
return m.parse(source).bind(function(c) { | |
var parser; | |
parser = f(c.value); | |
return parser.parse(c.source); | |
}); | |
}); | |
}; | |
Parser.prototype.bind = function(f) { | |
return Parser.bind(this, f); | |
}; | |
(function() { | |
var addMethods; | |
addMethods = require("./From").addMethods; | |
return addMethods(Parser); | |
})(); | |
exports.Parser = Parser; | |
exports.Message = Message; | |
exports.Continuation = Continuation; | |
}).call(null, modules["./Core"] = {}); | |
(function(exports) { | |
var Continuation, Failure, Message, Parser, Port, Result, Success, cloneRegexp, _ref, _ref1, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { | |
function ctor() { | |
this.constructor = child; | |
} | |
for (var key in parent) { | |
if (__hasProp.call(parent, key)) child[key] = parent[key]; | |
} | |
ctor.prototype = parent.prototype; | |
child.prototype = new ctor; | |
child.__super__ = parent.prototype; | |
return child; | |
}; | |
_ref = require("./Core"), Parser = _ref.Parser, Continuation = _ref.Continuation, Message = _ref.Message; | |
_ref1 = require("./Result"), Result = _ref1.Result, Success = _ref1.Success, Failure = _ref1.Failure; | |
Port = require("./Port").Port; | |
Parser.Exactly = function(_super) { | |
function Exactly(string) { | |
this.string = string; | |
} | |
__extends(Exactly, _super); | |
Exactly.prototype.parse = function(source) { | |
var cont, head, message, reason, rest; | |
source = Port.from(source); | |
head = source.slice(0, this.string.length); | |
if (head === this.string) { | |
rest = source.move(this.string.length); | |
cont = new Continuation(head, rest); | |
return new Success(cont); | |
} else { | |
reason = "Source didn't match: '" + this.string + "'"; | |
message = new Message(reason, source); | |
return new Failure(message); | |
} | |
}; | |
return Exactly; | |
}(Parser); | |
Parser.addConverter("String", function(str) { | |
return new Parser.Exactly(str); | |
}); | |
cloneRegexp = function(source) { | |
var destination, src; | |
src = source.source; | |
if (src.charAt(0) !== "^") { | |
src = "^" + src; | |
} | |
destination = new RegExp(src); | |
destination.global = source.global; | |
destination.ignoreCase = source.ignoreCase; | |
destination.multiline = source.multiline; | |
return destination; | |
}; | |
Parser.RegExp = function(_super) { | |
function RegExp(pattern, index) { | |
this._pattern = pattern; | |
this.index = index != null ? index : 0; | |
} | |
__extends(RegExp, _super); | |
RegExp.prototype.getPattern = function() { | |
return cloneRegexp(this._pattern); | |
}; | |
RegExp.prototype.parse = function(source) { | |
var cont, match, message, pattern, reason, rest, val; | |
source = Port.from(source); | |
pattern = this.getPattern(); | |
match = pattern.exec(source.slice()); | |
if (match != null) { | |
val = match[this.index]; | |
rest = source.move(match[0].length); | |
cont = new Continuation(val, rest); | |
return new Success(cont); | |
} else { | |
reason = "Source didn't match: /" + pattern.source + "/"; | |
message = new Message(reason, source); | |
return new Failure(message); | |
} | |
}; | |
return RegExp; | |
}(Parser); | |
Parser.addConverter("RegExp", function(str) { | |
return new Parser.RegExp(str); | |
}); | |
}).call(null, modules["./Matchers"] = {}); | |
(function(exports) { | |
var Any, Continuation, Failure, Location, Message, Or, Parser, Port, Result, Seq, Success, bind, mreturn, mzero, _ref, _ref1, _ref2, __slice = [].slice; | |
_ref = require("./Core"), Parser = _ref.Parser, Message = _ref.Message, Continuation = _ref.Continuation; | |
_ref1 = require("./Result"), Success = _ref1.Success, Failure = _ref1.Failure, Result = _ref1.Result; | |
bind = Parser.bind, mreturn = Parser.mreturn, mzero = Parser.mzero; | |
_ref2 = require("./Port"), Port = _ref2.Port, Location = _ref2.Location; | |
Parser.prototype.andThen = function(parser) { | |
return bind(this, function(v1) { | |
return bind(parser, function(v2) { | |
return mreturn([ v1, v2 ]); | |
}); | |
}); | |
}; | |
Parser.prototype.convert = function(converter) { | |
return this.bind(function(v) { | |
return new Parser.Succeed(converter(v)); | |
}); | |
}; | |
Parser.prototype.convertTo = function(Klass) { | |
return this.convert(function(v) { | |
return new Klass(v); | |
}); | |
}; | |
Seq = Parser.Seq = function(parsers) { | |
var cons, first, rest; | |
cons = function(a, b) { | |
return [ a ].concat(b); | |
}; | |
if (parsers.length === 0) { | |
return new Parser.Succeed([]); | |
} else { | |
first = parsers[0], rest = 2 <= parsers.length ? __slice.call(parsers, 1) : []; | |
return Parser.from(first).bind(function(head) { | |
return Seq(rest).bind(function(tail) { | |
return new Parser.Succeed(cons(head, tail)); | |
}); | |
}); | |
} | |
}; | |
Parser.addConverter("Array", Seq); | |
Or = Parser.Or = function(a, b) { | |
return new Parser(function(source) { | |
var result; | |
result = a.parse(source); | |
if (result.didSucceed) { | |
return result; | |
} else { | |
return b.parse(source); | |
} | |
}); | |
}; | |
Parser.prototype.or = function(other) { | |
return Or(this, other); | |
}; | |
Parser.prototype.maybe = function(v) { | |
return Or(this, new Parser.Succeed(v)); | |
}; | |
Any = Parser.Any = function(arr) { | |
var first, rest; | |
if (arr.length === 0) { | |
return new Parser.Fail("no candidates"); | |
} else if (arr.length === 1) { | |
return arr[0]; | |
} else if (arr.length === 2) { | |
return Or(arr[0], arr[1]); | |
} else { | |
first = arr[0], rest = 2 <= arr.length ? __slice.call(arr, 1) : []; | |
return Or(first, Any(rest)); | |
} | |
}; | |
Parser.prototype.onceOrMore = function() { | |
var cons, _this = this; | |
cons = function(a, b) { | |
return [ a ].concat(b); | |
}; | |
return this.bind(function(head) { | |
var parseRest; | |
parseRest = _this.onceOrMore().maybe([]); | |
return parseRest.bind(function(tail) { | |
return new Parser.Succeed(cons(head, tail)); | |
}); | |
}); | |
}; | |
Parser.prototype.zeroOrMore = function() { | |
var any; | |
any = this.onceOrMore(); | |
return any.maybe([]); | |
}; | |
Parser.prototype.precededBy = function(prefix) { | |
var _this = this; | |
return Parser.from(prefix).bind(function(_) { | |
return _this; | |
}); | |
}; | |
Parser.prototype.followedBy = function(suffix) { | |
return this.bind(function(v1) { | |
return Parser.from(suffix).bind(function(_) { | |
return mreturn(v1); | |
}); | |
}); | |
}; | |
Parser.prototype.surroundedBy = function(left, right) { | |
return this.precededBy(left).followedBy(right); | |
}; | |
Parser.prototype.is = function(test) { | |
return this.bind(function(v1) { | |
if (test(v1)) { | |
return mreturn(v1); | |
} else { | |
return new Parser.Fail("Failed predicate"); | |
} | |
}); | |
}; | |
Parser.prototype.isnt = function(test) { | |
return this.is(function(v) { | |
return !test(v); | |
}); | |
}; | |
Parser.prototype.separatedBy = function(comma) { | |
var squash, tail; | |
comma = Parser.from(comma); | |
squash = function(_arg) { | |
var a, b; | |
a = _arg[0], b = _arg[1]; | |
return [ a ].concat(b); | |
}; | |
tail = this.precededBy(comma).zeroOrMore(); | |
return this.andThen(tail).convert(squash); | |
}; | |
Parser.prototype.withLocation = function(fn) { | |
var _this = this; | |
return new Parser(function(_source) { | |
var start; | |
_source = Port.from(_source); | |
start = _source.getLocation(); | |
return _this.parse(_source).bind(function(cont) { | |
var end, next, source, value, _value; | |
source = cont.source, value = cont.value; | |
end = source.getLocation(); | |
_value = fn(value, start, end); | |
next = new Continuation(_value, source); | |
return new Success(next); | |
}); | |
}); | |
}; | |
}).call(null, modules["./Combinators"] = {}); | |
(function(exports) { | |
var Continuation, Failure, Location, Message, Parser, Port, Result, Success, _ref, _ref1, _ref2; | |
_ref = require("./Core"), Parser = _ref.Parser, Continuation = _ref.Continuation, Message = _ref.Message; | |
require("./Matchers"); | |
require("./Combinators"); | |
_ref1 = require("./Port"), Port = _ref1.Port, Location = _ref1.Location; | |
_ref2 = require("./Result"), Result = _ref2.Result, Success = _ref2.Success, Failure = _ref2.Failure; | |
exports.Parser = Parser; | |
exports.Continuation = Continuation; | |
exports.Message = Message; | |
exports.Result = Result; | |
exports.Success = Success; | |
exports.Failure = Failure; | |
exports.Port = Port; | |
exports.Location = Location; | |
}).call(null, modules["./Parser"] = {}); | |
return require("./Parser"); | |
}(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment