parser-combinators
v1.2.6
Published
A library of parser combinators, with which you can create your own parsers. The library will be continuously improved in time.
Maintainers
Readme
Parser Combinators
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
strictmode 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:
anybetweenexhaustmany(andzeroOrMany,oneOrMany,oneOrManyRed)mapoptionalregexsequencestring andstring (case-insensitive)
- Utility combinators:
referexpectexpectErasesurelytokenlookaround
- Ready-made value combinators:
spacesspacesPluswspacesbool(andboolP)int(andintP)real(andrealP)eof
- Recovery combinators:
recoverBySkippingCharsrecoverByAddingChars
- Whole parsers:
- Extended Backus-Naur Form (
EBNF) - JavaScript Object Notation (
JSON)
- Extended Backus-Naur Form (
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'))Example usage:
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.75Using 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
---------------^