2 var punctuation
= require("./punctuation");
4 // builds a string parser from a streaming character parser
5 exports
.makeParser
= makeParser
;
6 function makeParser(production
, errorHandler
) {
7 var errorHandler
= errorHandler
|| function (error
, text
) {
8 throw new Error(error
+ " while parsing " + JSON
.stringify(text
));
10 return function (text
/*, ...args*/) {
11 // the parser is a monadic state machine.
12 // each state is represented by a function that accepts
13 // a character. parse functions accept a callback (for forwarding the
14 // result) and return a state.
16 var state
= production
.apply(null, [function (_result
) {
18 return expectEof(function (error
) {
19 return errorHandler(error
, text
);
21 }].concat(Array
.prototype.slice
.call(arguments
, 1)));
22 // drive the state machine
23 Array
.prototype.forEach
.call(text
, function (letter
, i
) {
24 state
= state(letter
);
28 state
= state(""); // EOF
34 function expectEof(errback
) {
35 return function (character
) {
36 if (character
!== "") {
37 errback("Unexpected " + JSON
.stringify(character
));
39 return function noop() {
45 exports
.makeExpect
= makeExpect
;
46 function makeExpect(expected
) {
47 return function (callback
) {
48 return function (character
) {
49 if (character
=== expected
) {
50 return callback(character
);
52 return callback()(character
);
58 exports
.makeParseSome
= makeParseSome
;
59 function makeParseSome(expected
) {
60 var parseSome
= function (callback
) {
61 return function (character
) {
62 if (character
=== expected
) {
63 return parseRemaining(callback
);
65 return callback()(character
);
69 var parseRemaining
= makeParseAny(expected
);
73 exports
.makeParseAny
= makeParseAny
;
74 function makeParseAny(expected
) {
75 return function parseRemaining(callback
) {
76 return function (character
) {
77 if (character
=== expected
) {
78 return parseRemaining(callback
);
80 return callback(expected
)(character
);
86 exports
.makeDelimitedParser
= makeDelimitedParser
;
87 function makeDelimitedParser(parsePrevious
, parseDelimiter
) {
88 return function parseSelf(callback
, options
, terms
) {
90 return parsePrevious(function (term
) {
92 return callback(terms
);
94 terms
= terms
.concat([term
]);
95 return parseDelimiter(function (delimiter
) {
97 return parseSelf(callback
, options
, terms
);
99 return callback(terms
);
107 // used by parsers to determine whether the cursor is on a word break
108 exports
.isBreak
= isBreak
;
109 function isBreak(character
) {
110 return character
=== " " || character
=== "\n" || character
=== "";
113 exports
.isFinal
= isFinal
;
114 function isFinal(character
) {
115 return isBreak(character
) || punctuation
[character
];
118 // used by multiple modes
119 exports
.countPrimes
= countPrimes
;
120 function countPrimes(callback
, primes
) {
121 primes
= primes
|| 0;
122 return function (character
) {
123 if (character
=== "'") {
124 return countPrimes(callback
, primes
+ 1);
126 return callback(primes
)(character
);