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.
17 var state
= production
.apply(null, [function (_result
) {
19 return expectEof(function (error
) {
20 return errorHandler(error
, text
);
22 }].concat(Array
.prototype.slice
.call(arguments
, 1)));
23 // drive the state machine
24 Array
.prototype.forEach
.call(text
, function (letter
, i
) {
25 state
= state(letter
);
29 state
= state(""); // EOF
35 function expectEof(errback
) {
36 return function (character
) {
37 if (character
!== "") {
38 errback("Unexpected " + JSON
.stringify(character
));
40 return function noop() {
46 exports
.makeExpect
= makeExpect
;
47 function makeExpect(expected
) {
48 return function (callback
) {
49 return function (character
) {
50 if (character
=== expected
) {
51 return callback(character
);
53 return callback()(character
);
59 exports
.makeParseSome
= makeParseSome
;
60 function makeParseSome(parseOne
) {
61 var parseSome
= function (callback
) {
62 return parseOne(function (one
) {
64 return parseRemaining(callback
, [one
]);
70 var parseRemaining
= makeParseAny(parseOne
);
74 exports
.makeParseAny
= makeParseAny
;
75 function makeParseAny(parseOne
) {
76 return function parseRemaining(callback
, any
) {
78 return parseOne(function (one
) {
80 return parseRemaining(callback
, any
.concat([one
]));
88 exports
.makeDelimitedParser
= makeDelimitedParser
;
89 function makeDelimitedParser(parsePrevious
, parseDelimiter
) {
90 return function parseSelf(callback
, options
, terms
) {
92 return parsePrevious(function (term
) {
94 return callback(terms
);
96 terms
= terms
.concat([term
]);
97 return parseDelimiter(function (delimiter
) {
99 return parseSelf(callback
, options
, terms
);
101 return callback(terms
);
109 // used by parsers to determine whether the cursor is on a word break
110 exports
.isBreak
= isBreak
;
111 function isBreak(character
) {
112 return character
=== " " || character
=== "\n" || character
=== "";
115 exports
.isFinal
= isFinal
;
116 function isFinal(character
) {
117 return isBreak(character
) || punctuation
[character
];
120 // used by multiple modes
121 exports
.countPrimes
= countPrimes
;
122 function countPrimes(callback
, primes
, rewind
) {
123 primes
= primes
|| 0;
124 rewind
= rewind
|| function (state
) {
127 return function (character
) {
128 if (character
=== "'") {
129 return countPrimes(callback
, primes
+ 1, function (state
) {
130 return rewind(state
)("'");
133 return callback(primes
, rewind
)(character
);