Parser Combinators


!
NPM

A library of parser combinators, with which you can create your own parsers.
#### Parser combinators can be used for:
- Replacing complicated regular expressions with easy-to-understand parsers
- Incorporating custom languages into your application
- Introducing higher-order functions and parsing concepts
#### This package:
- Has full TypeScript support and is made with
strict mode on
- Is thoroughly tested
- Is made in the _Simplicity first_ philosophy
- Will be continuously improved in time
##### As of now it contains the following combinators:
- Standard combinators:
-
any
-
between
-
exhaust
-
many (and
zeroOrMany,
oneOrMany,
oneOrManyRed)
-
map
-
optional
-
regex
-
sequence
-
string and
string (case-insensitive)
- Utility combinators:
-
refer
-
expect
-
expectErase
-
surely
-
token
-
lookaround
- Ready-made value combinators:
-
spaces
-
spacesPlus
-
wspaces
-
bool (and
boolP)
-
int (and
intP)
-
real (and
realP)
-
eof
- Recovery combinators:
-
recoverBySkippingChars
-
recoverByAddingChars
- Whole parsers:
- Extended Backus-Naur Form (
EBNF)
- JavaScript Object Notation (
JSON)
##### Optimization remarks:
Combining many string parsers using an
any parser uses parser fusion.
This means that a parser of the form e.g.
any(str(...), ..., str()) is automatically converted into a search trie.
This drastically decreases the number of callbacks, and improves performance because all search strings are checked "at once" by going over the trie.
Nested
any parsers are also supported, as well as
stri parsers, so all of these undergo fusion:
any(str('QeQMTvqJuS'), str('IoOYSLNPlM'), str('SpFMUWpzHs'))
any(str('QeQMTvqJuS'), any(str('IoOYSLNPlM'), str('SpFMUWpzHs')))
any(str('QeQMTvqJuS'), stri('QeQMTvqJuS'), str('QeqmtabeacErEmTDUUIFcFpsAJhfwqXN'), str('SpFMUWpzHs'))
$3
##### Using standard combinators:
import { seq, str, any } from 'parser-combinators/parsers';
import { ParseText } from 'parser-combinators';
const parser = seq(str('a'), any(str('b'), str('c')));
const result = ParseText('ab', parser); // Will return ['a', 'b']
##### Using ready value combinators:
import { wspaces, str, realP, map } from 'parser-combinators/parsers';
import { ParseText } from 'parser-combinators';
const parser = map(
seq(wspaces, str('number:'), wspaces, realP, wspaces),
([,,, data]) => data
);
const result = ParseText(' number: 1.75 ', parser); // Will return 1.75
##### Using
ref to expand the parser's possibilities:
import { wspaces, str, realP, map } from 'parser-combinators/parsers';
import { ParseText } from 'parser-combinators';
const parser = ref(
map(
seq(wspaces, str('number:'), wspaces, realP, wspaces),
([,,, data]) => data
),
data => data > 1.5,
'The number must be over 1.5!'
);
const result = ParseText(' number: 1.25 ', parser); // Will throw a ParseError('The number must be over 1.5!')
##### Pretty messages available on parsing errors:
import { spacesPlus, str } from 'parser-combinators/parsers';
import { ParseText } from 'parser-combinators';
const parser = seq(
str('Lazy fox jumps'), spacesPlus, str('over'), spacesPlus, str('a lazy dog')
);
try {
const result = ParseText('Lazy fox jumps under a lazy dog', parser);
} catch (e) {
console.error(e.getPrettyErrorMessage());
}
Will write:
Parse error, expected over at char 15 (line 1, col 16):
Lazy fox jumps under a lazy dog
---------------^