monadic-parser.ts 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. * @author Koya Sakuma <koya.sakuma.work@gmail.com>
  6. **
  7. * Adapted from Parsimmon (https://github.com/jneen/parsimmon)
  8. * Copyright (c) 2011-present J. Adkisson (http://jneen.net).
  9. **/
  10. export class MonadicParser<A> {
  11. constructor(public _: MonadicParser.Action<A>) { }
  12. parse(input: string): MonadicParser.ParseResult<A> {
  13. const result = this.skip(MonadicParser.eof)._(input, 0);
  14. if (result.status) {
  15. return { success: true, value: result.value };
  16. }
  17. return { success: false, index: makeLineColumnIndex(input, result.furthest), expected: result.expected };
  18. };
  19. tryParse(str: string) {
  20. const result = this.parse(str);
  21. if (result.success) {
  22. return result.value;
  23. } else {
  24. const msg = formatError(str, result);
  25. const err = new Error(msg);
  26. throw err;
  27. }
  28. }
  29. or<B>(alternative: MonadicParser<B>): MonadicParser<A | B> {
  30. return MonadicParser.alt(this, alternative);
  31. }
  32. trim<B>(parser: MonadicParser<B> | string): MonadicParser<A> {
  33. return this.wrap(parser, parser);
  34. }
  35. wrap<L, R>(leftParser: MonadicParser<L> | string, rightParser: MonadicParser<R> | string): MonadicParser<A> {
  36. return seqPick(1,
  37. typeof leftParser === 'string' ? MonadicParser.string(leftParser) : leftParser,
  38. this,
  39. typeof rightParser === 'string' ? MonadicParser.string(rightParser) : rightParser);
  40. }
  41. thru<B>(wrapper: (p: MonadicParser<A>) => MonadicParser<B>) {
  42. return wrapper(this);
  43. }
  44. then<B>(next: MonadicParser<B>): MonadicParser<B> {
  45. return seqPick(1, this, next);
  46. }
  47. many() {
  48. return new MonadicParser((input, i) => {
  49. const accum: A[] = [];
  50. let result: MonadicParser.Result<A> | undefined = void 0;
  51. while (true) {
  52. result = mergeReplies(this._(input, i), result);
  53. if (result.status) {
  54. if (i === result.index) {
  55. throw new Error('infinite loop detected in .many() parser --- calling .many() on a parser which can accept zero characters is usually the cause');
  56. }
  57. i = result.index;
  58. accum.push(result.value);
  59. } else {
  60. return mergeReplies(makeSuccess(i, accum), result);
  61. }
  62. }
  63. });
  64. };
  65. times(min: number, _max?: number): MonadicParser<A[]> {
  66. const max = typeof _max === 'undefined' ? min : _max;
  67. return new MonadicParser((input, i) => {
  68. const accum: A[] = [];
  69. let result: MonadicParser.Result<A> | undefined = void 0;
  70. let prevResult: MonadicParser.Result<A> | undefined = void 0;
  71. let times: number;
  72. for (times = 0; times < min; times++) {
  73. result = this._(input, i);
  74. prevResult = mergeReplies(result, prevResult);
  75. if (result.status) {
  76. i = result.index;
  77. accum.push(result.value);
  78. } else {
  79. return prevResult as any;
  80. }
  81. }
  82. for (; times < max; times += 1) {
  83. result = this._(input, i);
  84. prevResult = mergeReplies(result, prevResult);
  85. if (result.status) {
  86. i = result.index;
  87. accum.push(result.value);
  88. } else {
  89. break;
  90. }
  91. }
  92. return mergeReplies(makeSuccess(i, accum), prevResult);
  93. });
  94. };
  95. result<B>(res: B) {
  96. return this.map(() => res);
  97. };
  98. atMost(n: number) {
  99. return this.times(0, n);
  100. };
  101. atLeast(n: number) {
  102. return MonadicParser.seq(this.times(n), this.many()).map(r => [...r[0], ...r[1]]);
  103. };
  104. map<B>(f: (a: A) => B): MonadicParser<B> {
  105. return new MonadicParser((input, i) => {
  106. const result = this._(input, i);
  107. if (!result.status) {
  108. return result;
  109. }
  110. return mergeReplies(makeSuccess(result.index, f(result.value)), result);
  111. });
  112. }
  113. skip<B>(next: MonadicParser<B>): MonadicParser<A> {
  114. return seqPick(0, this, next);
  115. }
  116. mark(): MonadicParser<MonadicParser.Mark<A>> {
  117. return MonadicParser.seq(MonadicParser.index, this, MonadicParser.index).map(r => ({ start: r[0], value: r[1], end: r[2] }));
  118. }
  119. node(name: string): MonadicParser<MonadicParser.Node<A>> {
  120. return MonadicParser.seq(MonadicParser.index, this, MonadicParser.index).map(r => ({ name, start: r[0], value: r[1], end: r[2] }));
  121. };
  122. sepBy<B>(separator: MonadicParser<B>): MonadicParser<A[]> {
  123. return MonadicParser.sepBy(this, separator);
  124. }
  125. sepBy1<B>(separator: MonadicParser<B>): MonadicParser<A[]> {
  126. return MonadicParser.sepBy1(this, separator);
  127. }
  128. lookahead<B>(x: MonadicParser<B>) {
  129. return this.skip(MonadicParser.lookahead(x));
  130. };
  131. notFollowedBy<B>(x: MonadicParser<B>) {
  132. return this.skip(MonadicParser.notFollowedBy(x));
  133. };
  134. desc(expected: string) {
  135. return new MonadicParser((input, i) => {
  136. const reply = this._(input, i);
  137. if (!reply.status) {
  138. reply.expected = [expected];
  139. }
  140. return reply;
  141. });
  142. };
  143. fallback<B>(result: B) {
  144. return this.or(MonadicParser.succeed(result));
  145. };
  146. ap<B>(other: MonadicParser<(x: A) => B>): MonadicParser<B> {
  147. return MonadicParser.seq(other, this).map(([f, x]) => f(x));
  148. };
  149. chain<B>(f: (a: A) => MonadicParser<B>): MonadicParser<B> {
  150. return new MonadicParser<B>((input, i) => {
  151. const result = this._(input, i);
  152. if (!result.status) {
  153. return result as any;
  154. }
  155. const nextParser = f(result.value);
  156. return mergeReplies(nextParser._(input, result.index), result);
  157. });
  158. };
  159. }
  160. export namespace MonadicParser {
  161. export type Action<T> = (input: string, i: number) => MonadicParser.Result<T>
  162. export type ParseResult<T> = ParseSuccess<T> | ParseFailure;
  163. export interface Index {
  164. /** zero-based character offset */
  165. offset: number;
  166. /** one-based line offset */
  167. line: number;
  168. /** one-based column offset */
  169. column: number;
  170. }
  171. export interface ParseSuccess<T> {
  172. success: true,
  173. value: T
  174. }
  175. export interface ParseFailure {
  176. success: false,
  177. index: Index,
  178. expected: string[],
  179. }
  180. export interface Mark<T> {
  181. start: Index;
  182. end: Index;
  183. value: T;
  184. }
  185. export interface Node<T> extends Mark<T> {
  186. name: string
  187. }
  188. export interface Success<T> {
  189. status: true,
  190. value: T,
  191. index: number
  192. }
  193. export interface Failure {
  194. status: false,
  195. furthest: number,
  196. expected: string[]
  197. }
  198. export type Result<T> = Success<T> | Failure
  199. export function seqMap<A, B>(a: MonadicParser<A>, b: MonadicParser<B>, c: any) {
  200. const args = [].slice.call(arguments);
  201. if (args.length === 0) {
  202. throw new Error('seqMap needs at least one argument');
  203. }
  204. const mapper = args.pop();
  205. assertFunction(mapper);
  206. return seq.apply(null, args).map(function (results: any) {
  207. return mapper.apply(null, results);
  208. });
  209. }
  210. export function createLanguage(parsers: any) {
  211. const language: any = {};
  212. for (const key of Object.keys(parsers)) {
  213. (function (key) {
  214. language[key] = lazy(() => parsers[key](language));
  215. })(key);
  216. }
  217. return language;
  218. }
  219. export function seq<A>(a: MonadicParser<A>): MonadicParser<[A]>
  220. export function seq<A, B>(a: MonadicParser<A>, b: MonadicParser<B>): MonadicParser<[A, B]>
  221. export function seq<A, B, C>(a: MonadicParser<A>, b: MonadicParser<B>, c: MonadicParser<C>): MonadicParser<[A, B, C]>
  222. export function seq<A, B, C, D>(a: MonadicParser<A>, b: MonadicParser<B>, c: MonadicParser<C>, d: MonadicParser<D>): MonadicParser<[A, B, C, D]>
  223. export function seq<A, B, C, D, E>(a: MonadicParser<A>, b: MonadicParser<B>, c: MonadicParser<C>, d: MonadicParser<D>, e: MonadicParser<E>): MonadicParser<[A, B, C, D, E]>
  224. export function seq<T>(...parsers: MonadicParser<T>[]): MonadicParser<T[]>
  225. export function seq(...parsers: MonadicParser<any>[]): MonadicParser<any[]> {
  226. const numParsers = parsers.length;
  227. return new MonadicParser<any[]>((input, index) => {
  228. let result: MonadicParser.Result<any> | undefined;
  229. const accum = new Array(numParsers);
  230. let i = index;
  231. for (let j = 0; j < numParsers; j++) {
  232. result = mergeReplies(parsers[j]._(input, i), result);
  233. if (!result.status) {
  234. return result;
  235. }
  236. accum[j] = result.value;
  237. i = result.index;
  238. }
  239. return mergeReplies(makeSuccess(i, accum), result);
  240. });
  241. }
  242. export function alt<A>(a: MonadicParser<A>): MonadicParser<A>
  243. export function alt<A, B>(a: MonadicParser<A>, b: MonadicParser<B>): MonadicParser<A | B>
  244. export function alt<A, B, C>(a: MonadicParser<A>, b: MonadicParser<B>, c: MonadicParser<C>): MonadicParser<A | B | C>
  245. export function alt<A, B, C, D>(a: MonadicParser<A>, b: MonadicParser<B>, c: MonadicParser<C>, d: MonadicParser<D>): MonadicParser<A | B | C | D>
  246. export function alt<A, B, C, D, E>(a: MonadicParser<A>, b: MonadicParser<B>, c: MonadicParser<C>, d: MonadicParser<D>, e: MonadicParser<E>): MonadicParser<A | B | C | D | E>
  247. export function alt<T>(...parsers: MonadicParser<T>[]): MonadicParser<T[]>
  248. export function alt(...parsers: MonadicParser<any>[]): MonadicParser<any> {
  249. const numParsers = parsers.length;
  250. if (numParsers === 0) {
  251. return fail('zero alternates');
  252. }
  253. return new MonadicParser((input, i) => {
  254. let result: MonadicParser.Result<any> | undefined;
  255. for (let j = 0; j < parsers.length; j++) {
  256. result = mergeReplies(parsers[j]._(input, i), result);
  257. if (result.status) {
  258. return result;
  259. }
  260. }
  261. return result!;
  262. });
  263. }
  264. export function sepBy<A, B>(parser: MonadicParser<A>, separator: MonadicParser<B>): MonadicParser<A[]> {
  265. return sepBy1(parser, separator).or(succeed([]));
  266. }
  267. export function sepBy1<A, B>(parser: MonadicParser<A>, separator: MonadicParser<B>) {
  268. const pairs = separator.then(parser).many();
  269. return seq(parser, pairs).map(r => [r[0], ...r[1]]);
  270. }
  271. export function string(str: string) {
  272. const expected = `'${str}'`;
  273. if (str.length === 1) {
  274. const code = str.charCodeAt(0);
  275. return new MonadicParser((input, i) => input.charCodeAt(i) === code ? makeSuccess(i + 1, str) : makeFailure(i, expected));
  276. }
  277. return new MonadicParser((input, i) => {
  278. const j = i + str.length;
  279. if (input.slice(i, j) === str) return makeSuccess(j, str);
  280. else return makeFailure(i, expected);
  281. });
  282. }
  283. function flags(re: RegExp) {
  284. const s = '' + re;
  285. return s.slice(s.lastIndexOf('/') + 1);
  286. }
  287. function anchoredRegexp(re: RegExp) {
  288. return RegExp('^(?:' + re.source + ')', flags(re));
  289. }
  290. export function regexp(re: RegExp, group = 0) {
  291. const anchored = anchoredRegexp(re);
  292. const expected = '' + re;
  293. return new MonadicParser((input, i) => {
  294. const match = anchored.exec(input.slice(i));
  295. if (match) {
  296. if (0 <= group && group <= match.length) {
  297. const fullMatch = match[0];
  298. const groupMatch = match[group];
  299. return makeSuccess(i + fullMatch.length, groupMatch);
  300. }
  301. const message = `invalid match group (0 to ${match.length}) in ${expected}`;
  302. return makeFailure(i, message);
  303. }
  304. return makeFailure(i, expected);
  305. });
  306. }
  307. export function succeed<A>(value: A) {
  308. return new MonadicParser((input, i) => makeSuccess(i, value));
  309. }
  310. export function fail(expected: string): MonadicParser<any> {
  311. return new MonadicParser((input, i) => makeFailure(i, expected));
  312. }
  313. export function lookahead<A>(x: MonadicParser<A> | string | RegExp): MonadicParser<null> {
  314. if (isParser(x)) {
  315. return new MonadicParser((input, i) => {
  316. const result = x._(input, i);
  317. if (result.status) {
  318. result.index = i;
  319. result.value = null as any;
  320. }
  321. return result as any;
  322. });
  323. } else if (typeof x === 'string') {
  324. return lookahead(string(x));
  325. } else if (x instanceof RegExp) {
  326. return lookahead(regexp(x));
  327. }
  328. throw new Error('not a string, regexp, or parser: ' + x);
  329. }
  330. export function notFollowedBy<A>(parser: MonadicParser<A>): MonadicParser<null> {
  331. return new MonadicParser((input, i) => {
  332. const result = parser._(input, i);
  333. return result.status
  334. ? makeFailure(i, 'not "' + input.slice(i, result.index) + '"')
  335. : makeSuccess(i, null);
  336. });
  337. }
  338. export function test(predicate: (char: string) => boolean): MonadicParser<string> {
  339. return new MonadicParser((input, i) => {
  340. const char = input.charAt(i);
  341. if (i < input.length && predicate(char)) {
  342. return makeSuccess(i + 1, char);
  343. } else {
  344. return makeFailure(i, 'a character ' + predicate);
  345. }
  346. });
  347. }
  348. export function oneOf(str: string) {
  349. return test(ch => str.indexOf(ch) >= 0);
  350. }
  351. export function noneOf(str: string) {
  352. return test(ch => str.indexOf(ch) < 0);
  353. }
  354. export function range(begin: string, end: string) {
  355. return test(ch => begin <= ch && ch <= end).desc(begin + '-' + end);
  356. }
  357. export function takeWhile(predicate: (ch: string) => boolean) {
  358. return new MonadicParser((input, i) => {
  359. let j = i;
  360. while (j < input.length && predicate(input.charAt(j))) {
  361. j++;
  362. }
  363. return makeSuccess(j, input.slice(i, j));
  364. });
  365. }
  366. export function lazy<T>(f: () => MonadicParser<T>) {
  367. const parser = new MonadicParser((input, i) => {
  368. const a = f()._;
  369. parser._ = a;
  370. return a(input, i);
  371. });
  372. return parser;
  373. }
  374. export function empty() {
  375. return fail('empty');
  376. }
  377. export const index = new MonadicParser(function (input, i) {
  378. return makeSuccess(i, makeLineColumnIndex(input, i));
  379. });
  380. export const anyChar = new MonadicParser<string>((input, i) => {
  381. if (i >= input.length) {
  382. return makeFailure(i, 'any character');
  383. }
  384. return makeSuccess(i + 1, input.charAt(i));
  385. });
  386. export const all = new MonadicParser(function (input, i) {
  387. return makeSuccess(input.length, input.slice(i));
  388. });
  389. export const eof = new MonadicParser(function (input, i) {
  390. if (i < input.length) {
  391. return makeFailure(i, 'EOF');
  392. }
  393. return makeSuccess(i, null);
  394. });
  395. export const digit = regexp(/[0-9]/).desc('a digit');
  396. export const digits = regexp(/[0-9]*/).desc('optional digits');
  397. export const letter = regexp(/[a-z]/i).desc('a letter');
  398. export const letters = regexp(/[a-z]*/i).desc('optional letters');
  399. export const optWhitespace = regexp(/\s*/).desc('optional whitespace');
  400. export const whitespace = regexp(/\s+/).desc('whitespace');
  401. export const cr = string('\r');
  402. export const lf = string('\n');
  403. export const crlf = string('\r\n');
  404. export const newline = alt(crlf, lf, cr).desc('newline');
  405. export const end = alt(newline, eof);
  406. export function of<A>(value: A) {
  407. return succeed(value);
  408. }
  409. export function regex(re: RegExp) {
  410. return regexp(re);
  411. }
  412. }
  413. function seqPick(idx: number, ...parsers: MonadicParser<any>[]): MonadicParser<any> {
  414. const numParsers = parsers.length;
  415. return new MonadicParser<any[]>((input, index) => {
  416. let result: MonadicParser.Result<any> | undefined;
  417. let picked: any;
  418. let i = index;
  419. for (let j = 0; j < numParsers; j++) {
  420. result = mergeReplies(parsers[j]._(input, i), result);
  421. if (!result.status) {
  422. return result;
  423. }
  424. if (idx === j) picked = result.value;
  425. i = result.index;
  426. }
  427. return mergeReplies(makeSuccess(i, picked), result);
  428. });
  429. }
  430. function makeSuccess<T>(index: number, value: T): MonadicParser.Success<T> {
  431. return { status: true, index, value };
  432. }
  433. function makeFailure(index: number, expected: string): MonadicParser.Failure {
  434. return { status: false, furthest: index, expected: [expected] };
  435. }
  436. function mergeReplies<A, B>(result: MonadicParser.Result<A>, last?: MonadicParser.Result<B>): MonadicParser.Result<A> {
  437. if (!last || result.status || last.status || result.furthest > last.furthest) {
  438. return result;
  439. }
  440. const expected = result.furthest === last.furthest
  441. ? unsafeUnion(result.expected, last.expected)
  442. : last.expected;
  443. return { status: result.status, furthest: last.furthest, expected };
  444. }
  445. function makeLineColumnIndex(input: string, i: number): MonadicParser.Index {
  446. const lines = input.slice(0, i).split('\n');
  447. // Note that unlike the character offset, the line and column offsets are
  448. // 1-based.
  449. const lineWeAreUpTo = lines.length;
  450. const columnWeAreUpTo = lines[lines.length - 1].length + 1;
  451. return { offset: i, line: lineWeAreUpTo, column: columnWeAreUpTo };
  452. }
  453. function formatExpected(expected: string[]) {
  454. if (expected.length === 1) {
  455. return expected[0];
  456. }
  457. return 'one of ' + expected.join(', ');
  458. }
  459. function formatGot(input: string, error: MonadicParser.ParseFailure) {
  460. const index = error.index;
  461. const i = index.offset;
  462. if (i === input.length) {
  463. return ', got the end of the input';
  464. }
  465. const prefix = i > 0 ? '\'...' : '\'';
  466. const suffix = input.length - i > 12 ? '...\'' : '\'';
  467. return ` at line ${index.line} column ${index.column}, got ${prefix}${input.slice(i, i + 12)}${suffix}`;
  468. }
  469. function formatError(input: string, error: MonadicParser.ParseFailure) {
  470. return `expected ${formatExpected(error.expected)}${formatGot(input, error)}`;
  471. }
  472. function unsafeUnion(xs: string[], ys: string[]) {
  473. const xn = xs.length;
  474. const yn = ys.length;
  475. if (xn === 0) return ys;
  476. else if (yn === 0) return xs;
  477. const set = new Set<string>();
  478. const ret: string[] = [];
  479. for (let i = 0; i < xn; i++) {
  480. if (!set.has(xs[i])) {
  481. ret[ret.length] = xs[i];
  482. set.add(xs[i]);
  483. }
  484. }
  485. for (let i = 0; i < yn; i++) {
  486. if (!set.has(ys[i])) {
  487. ret[ret.length] = ys[i];
  488. set.add(ys[i]);
  489. }
  490. }
  491. ret.sort();
  492. return ret;
  493. }
  494. function isParser(obj: any): obj is MonadicParser<any> {
  495. return obj instanceof MonadicParser;
  496. }
  497. function assertFunction(x: any) {
  498. if (typeof x !== 'function') {
  499. throw new Error('not a function: ' + x);
  500. }
  501. }