A couple more fixes and edits

This commit is contained in:
Daniel Holden
2014-01-21 11:29:08 +00:00
parent 172d4ae5d9
commit 51dbf66b50
4 changed files with 223 additions and 237 deletions

237
README.md
View File

@@ -1,13 +1,13 @@
Micro Parser Combinators
========================
_mpc_ is a lightweight but powerful Parser Combinator library for C.
_mpc_ is a lightweight and powerful Parser Combinator library for C.
Using _mpc_ might be of interest to you if you are...
* Building a new programming language
* Building a new data format
* Parsing an existing programming languages
* Parsing an existing programming language
* Parsing an existing data format
* Embedding a Domain Specific Language
* Implementing [Greenspun's Tenth Rule](http://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule)
@@ -21,15 +21,15 @@ Features
* Easy to Integrate (One Source File in ANSI C)
* Error Messages
* Regular Expression Parser Generator
* Grammar Parser Generator
* Language/Grammar Parser Generator
Alternatives
------------
The current main alternative C based parser combinator is a branch of [Cesium3](https://github.com/wbhart/Cesium3/tree/combinators).
The current main alternative in C based parser combinators is a branch of [Cesium3](https://github.com/wbhart/Cesium3/tree/combinators).
_mpc_ provides a number of features that this project does not offer, but it also overcomes a number of potential downsides:
_mpc_ provides a number of features that this project does not offer, and also overcomes a number of potential downsides:
* _mpc_ Works for Generic Types
* _mpc_ Doesn't rely on Boehm-Demers-Weiser Garbage Collection
@@ -38,39 +38,40 @@ _mpc_ provides a number of features that this project does not offer, but it als
View From the Top
-----------------
=================
In this example I create a parser for a basic maths language. The function `parse_maths` takes as input some mathematical expression and outputs an instance of `mpc_ast_t`.
```c
#include "mpc.h"
mpc_ast_t* parse_maths(const char* input) {
void parse_maths(const char *input) {
mpc_parser_t* Expr = mpc_new("expression");
mpc_parser_t* Prod = mpc_new("product");
mpc_parser_t* Value = mpc_new("value");
mpc_parser_t* Maths = mpc_new("maths");
mpc_parser_t *Expr = mpc_new("expression");
mpc_parser_t *Prod = mpc_new("product");
mpc_parser_t *Value = mpc_new("value");
mpc_parser_t *Maths = mpc_new("maths");
mpca_lang(
" \
expression : <product> (('+' | '-') <product>)*; \
product : <value> (('*' | '/') <value> )*; \
value : /[0-9]+/ | '(' <expression> ')'; \
maths : /^/ <expression> /$/; \
" \
expression : <product> (('+' | '-') <product>)*; \
product : <value> (('*' | '/') <value> )*; \
value : /[0-9]+/ | '(' <expression> ')'; \
maths : /^/ <expression> /$/; \
",
Expr, Prod, Value, Maths);
mpc_result_t r;
mpc_result_t r;
if (!mpc_parse("<parse_maths>", input, Maths, &r)) {
mpc_ast_print(r.output);
mpc_ast_delete(r.output);
} else {
mpc_err_print(r.error);
mpc_err_delete(r.error);
exit(EXIT_FAILURE);
}
mpc_cleanup(4, Expr, Prod, Value, Maths);
return r.output;
}
```
@@ -94,9 +95,11 @@ If you were to input `"(4 * 2 * 11 + 2) - 5"` into this function, the `mpc_ast_t
product|value|regex: '5'
```
Getting Started
===============
View From the Bottom
--------------------
Introduction
------------
Parser Combinators are structures that encode how to parse a particular language. They can be combined using intuitive operators to create new parsers of increasing complexity. Using these operators detailed grammars and languages can be parsed and processed in a quick, efficient, and easy way.
@@ -105,7 +108,7 @@ The trick behind Parser Combinators is the observation that by structuring the l
As is shown in the above example _mpc_ takes this one step further, and actually allows you to specify the grammar directly, or to built up parsers using library functions.
Parsers
Parsing
-------
The Parser Combinator type in _mpc_ is `mpc_parser_t`. This encodes a function that attempts to parse some string and, if successful, returns a pointer to some data. Otherwise it returns some error. A parser can be run using `mpc_parse`.
@@ -113,24 +116,24 @@ The Parser Combinator type in _mpc_ is `mpc_parser_t`. This encodes a function t
* * *
```c
int mpc_parse(const char* filename, const char* string, mpc_parser_t* p, mpc_result_t* r);
int mpc_parse(const char *filename, const char *string, mpc_parser_t *p, mpc_result_t *r);
```
This function returns `1` on success and `0` on failure. It takes as input some parser `p`, some input `string`, and some `filename`. It outputs into `r` the result of the parse - which is either a pointer to some data object, or an error. The type `mpc_result_t` is a union type defined as follows.
```c
typedef union {
mpc_err_t* error;
mpc_val_t* output;
mpc_err_t *error;
mpc_val_t *output;
} mpc_result_t;
```
where `mpc_val_t` is synonymous with `void*` and simply represents some pointer to data - the exact type of which is dependant on the parser. Some variations on the above also exist. For almost all of the built-in and basic parsers the return type for a successful parser will be `char*`.
where `mpc_val_t` is synonymous with `void *` and simply represents some pointer to data - the exact type of which is dependant on the parser. Some variations on the above also exist. For almost all of the built-in and basic parsers the return type for a successful parser will be `char *`.
* * *
```c
int mpc_fparse(const char* filename, FILE* file, mpc_parser_t* p, mpc_result_t* r);
int mpc_parse_file(const char *filename, FILE *file, mpc_parser_t *p, mpc_result_t *r);
```
Parses the contents of `file` with parser `p` and returns the result in `r`. Returns `1` on success and `0` on failure. This is also the correct method to parse input from pipes or streams.
@@ -138,7 +141,7 @@ Parses the contents of `file` with parser `p` and returns the result in `r`. Ret
* * *
```c
int mpc_fparse_contents(const char* filename, mpc_parser_t* p, mpc_result_t* r);
int mpc_parse_contents(const char* filename, mpc_parser_t *p, mpc_result_t* r);
```
Opens file `filename` and parsers contents with `p`. Returns result in `r`. Returns `1` on success and `0` on failure;
@@ -154,7 +157,7 @@ All the following functions return basic parsers. All of those parsers return a
* * *
```c
mpc_parser_t* mpc_any(void);
mpc_parser_t *mpc_any(void);
```
Matches any individual character
@@ -162,7 +165,7 @@ Matches any individual character
* * *
```c
mpc_parser_t* mpc_char(char c);
mpc_parser_t *mpc_char(char c);
```
Matches a single given character `c`
@@ -170,7 +173,7 @@ Matches a single given character `c`
* * *
```c
mpc_parser_t* mpc_range(char s, char e);
mpc_parser_t *mpc_range(char s, char e);
```
Matches any single given character in the range `s` to `e` (inclusive)
@@ -178,7 +181,7 @@ Matches any single given character in the range `s` to `e` (inclusive)
* * *
```c
mpc_parser_t* mpc_oneof(const char* s);
mpc_parser_t *mpc_oneof(const char* s);
```
Matches any single given character in the string `s`
@@ -186,14 +189,14 @@ Matches any single given character in the string `s`
* * *
```c
mpc_parser_t* mpc_noneof(const char* s);
mpc_parser_t *mpc_noneof(const char* s);
```
Matches any single given character not in the string `s`
* * *
```c
mpc_parser_t* mpc_satisfy(int(*f)(char));
mpc_parser_t *mpc_satisfy(int(*f)(char));
```
Matches any single given character satisfying function `f`
@@ -201,7 +204,7 @@ Matches any single given character satisfying function `f`
* * *
```c
mpc_parser_t* mpc_string(const char* s);
mpc_parser_t *mpc_string(const char* s);
```
Matches exactly the string `s`
@@ -214,7 +217,7 @@ Several other functions exist that return basic parsers with some other special
* * *
```c
mpc_parser_t* mpc_pass(void);
mpc_parser_t *mpc_pass(void);
```
Consumes no input, always successful, returns `NULL`
@@ -222,7 +225,8 @@ Consumes no input, always successful, returns `NULL`
* * *
```c
mpc_parser_t* mpc_fail(const char* m);
mpc_parser_t *mpc_fail(const char* m);
mpc_parser_t *mpc_failf(const char* fmt, ...);
```
Consumes no input, always fails with message `m`.
@@ -230,7 +234,7 @@ Consumes no input, always fails with message `m`.
* * *
```c
mpc_parser_t* mpc_failf(const char* fmt, ...);
mpc_parser_t *mpc_failf(const char* fmt, ...);
```
Consumes no input, always fails with formatted message given by `fmt` and following parameters.
@@ -238,7 +242,7 @@ Consumes no input, always fails with formatted message given by `fmt` and follow
* * *
```c
mpc_parser_t* mpc_lift(mpc_ctor_t f);
mpc_parser_t *mpc_lift(mpc_ctor_t f);
```
Consumes no input, always successful, returns the result of function `f`
@@ -246,7 +250,7 @@ Consumes no input, always successful, returns the result of function `f`
* * *
```c
mpc_parser_t* mpc_lift_val(mpc_val_t* x);
mpc_parser_t *mpc_lift_val(mpc_val_t* x);
```
Consumes no input, always successful, returns `x`
@@ -264,7 +268,8 @@ Here are the main combinators and how to use then.
* * *
```c
mpc_parser_t* mpc_expect(mpc_parser_t* a, const char* e);
mpc_parser_t *mpc_expect(mpc_parser_t *a, const char* e);
mpc_parser_t *mpc_expectf(mpc_parser_t *a, const char* fmt, ...);
```
Returns a parser that runs `a`, and on success returns the result of `a`, while on failure reports that `e` was expected.
@@ -272,8 +277,8 @@ Returns a parser that runs `a`, and on success returns the result of `a`, while
* * *
```c
mpc_parser_t* mpc_apply(mpc_parser_t* a, mpc_apply_t f);
mpc_parser_t* mpc_apply_to(mpc_parser_t* a, mpc_apply_to_t f, void* x);
mpc_parser_t *mpc_apply(mpc_parser_t *a, mpc_apply_t f);
mpc_parser_t *mpc_apply_to(mpc_parser_t *a, mpc_apply_to_t f, void* x);
```
Returns a parser that applies function `f` (optionality taking extra input `x`) to the result of parser `a`.
@@ -281,8 +286,8 @@ Returns a parser that applies function `f` (optionality taking extra input `x`)
* * *
```c
mpc_parser_t* mpc_not(mpc_parser_t* a, mpc_dtor_t da);
mpc_parser_t* mpc_not_lift(mpc_parser_t* a, mpc_dtor_t da, mpc_ctor_t lf);
mpc_parser_t *mpc_not(mpc_parser_t *a, mpc_dtor_t da);
mpc_parser_t *mpc_not_lift(mpc_parser_t *a, mpc_dtor_t da, mpc_ctor_t lf);
```
Returns a parser with the following behaviour. If parser `a` succeeds, then it fails and consumes no input. If parser `a` fails, then it succeeds, consumes no input and returns `NULL` (or the result of lift function `lf`). Destructor `da` is used to destroy the result of `a` on success.
@@ -290,8 +295,8 @@ Returns a parser with the following behaviour. If parser `a` succeeds, then it f
* * *
```c
mpc_parser_t* mpc_maybe(mpc_parser_t* a);
mpc_parser_t* mpc_maybe_lift(mpc_parser_t* a, mpc_ctor_t lf);
mpc_parser_t *mpc_maybe(mpc_parser_t *a);
mpc_parser_t *mpc_maybe_lift(mpc_parser_t *a, mpc_ctor_t lf);
```
Returns a parser that runs `a`. If `a` is successful then it returns the result of `a`. If `a` is unsuccessful then it succeeds, but returns `NULL` (or the result of `lf`).
@@ -299,7 +304,7 @@ Returns a parser that runs `a`. If `a` is successful then it returns the result
* * *
```c
mpc_parser_t* mpc_many(mpc_fold_t f, mpc_parser_t* a);
mpc_parser_t *mpc_many(mpc_fold_t f, mpc_parser_t *a);
```
Keeps running `a` until it fails. Results are combined using fold function `f`. See the _Function Types_ section for more details.
@@ -307,7 +312,7 @@ Keeps running `a` until it fails. Results are combined using fold function `f`.
* * *
```c
mpc_parser_t* mpc_many1(mpc_fold_t f, mpc_parser_t* a);
mpc_parser_t *mpc_many1(mpc_fold_t f, mpc_parser_t *a);
```
Attempts to run `a` one or more times. Results are combined with fold function `f`.
@@ -315,7 +320,7 @@ Attempts to run `a` one or more times. Results are combined with fold function `
* * *
```c
mpc_parser_t* mpc_count(int n, mpc_fold_t f, mpc_parser_t* a, mpc_dtor_t da);
mpc_parser_t *mpc_count(int n, mpc_fold_t f, mpc_parser_t *a, mpc_dtor_t da);
```
Attempts to run `a` exactly `n` times. If this fails, any partial results are destructed with `da`. If successful results of `a` are combined using fold function `f`.
@@ -323,7 +328,7 @@ Attempts to run `a` exactly `n` times. If this fails, any partial results are de
* * *
```c
mpc_parser_t* mpc_or(int n, ...);
mpc_parser_t *mpc_or(int n, ...);
```
Attempts to run `n` parsers in sequence, returning the first one that succeeds. If all fail, returns an error.
@@ -331,7 +336,7 @@ Attempts to run `n` parsers in sequence, returning the first one that succeeds.
* * *
```c
mpc_parser_t* mpc_and(int n, mpc_fold_t f, ...);
mpc_parser_t *mpc_and(int n, mpc_fold_t f, ...);
```
Attempts to run `n` parsers in sequence, returning the fold of the results using fold function `f`. First parsers must be specified, followed by destructors for each parser, excluding the final parser. These are used in case of partial success. For example: `mpc_and(3, mpcf_strfold, mpc_char('a'), mpc_char('b'), mpc_char('c'), free, free);` would attempt to match `'a'` followed by `'b'` followed by `'c'`, and if successful would concatenate them using `mpcf_strfold`. Otherwise would use `free` on the partial results.
@@ -339,7 +344,7 @@ Attempts to run `n` parsers in sequence, returning the fold of the results using
* * *
```c
mpc_parser_t* mpc_predictive(mpc_parser_t* a);
mpc_parser_t *mpc_predictive(mpc_parser_t *a);
```
Returns a parser that runs `a` with backtracking disabled. This means if `a` consumes any input, it will not be reverted, even on failure. Turning backtracking off has good performance benefits for grammars which are `LL(1)`. These are grammars where the first character completely determines the parse result - such as the decision of parsing either a C identifier, number, or string literal. This option should not be used for non `LL(1)` grammars or it will produce incorrect results or crash the parser.
@@ -412,13 +417,13 @@ Then we can actually specify the grammar using combinators to say how the basic
```c
char* parse_ident(char* input) {
mpc_parser_t* alpha = mpc_or(2, mpc_range('a', 'z'), mpc_range('A', 'Z'));
mpc_parser_t* digit = mpc_range('0', '9');
mpc_parser_t* underscore = mpc_char('_');
mpc_parser_t *alpha = mpc_or(2, mpc_range('a', 'z'), mpc_range('A', 'Z'));
mpc_parser_t *digit = mpc_range('0', '9');
mpc_parser_t *underscore = mpc_char('_');
mpc_parser_t* ident0 = mpc_or(2, alpha, underscore);
mpc_parser_t* ident1 = mpc_many(strfold, mpc_or(3, alpha, digit, underscore));
mpc_parser_t* ident = mpc_and(2, strfold, ident0, ident1, free);
mpc_parser_t *ident0 = mpc_or(2, alpha, underscore);
mpc_parser_t *ident1 = mpc_many(strfold, mpc_or(3, alpha, digit, underscore));
mpc_parser_t *ident = mpc_and(2, strfold, ident0, ident1, free);
mpc_result_t r;
if (!mpc_parse("<parse_ident>", input, ident, &r)) {
@@ -444,7 +449,7 @@ Building parsers in the above way can have issues with self-reference or cyclic-
* * *
```c
mpc_parser_t* mpc_new(const char* name);
mpc_parser_t *mpc_new(const char* name);
```
This will construct a parser called `name` which can then be used by others, including itself, without ownership being transfered. Any parser created using `mpc_new` is said to be _retained_. This means it will behave differently to a normal parser when referenced. When deleting a parser that includes a _retained_ parser, the _retained_ parser it will not be deleted along with it. To delete a retained parser `mpc_delete` must be used on it directly.
@@ -454,7 +459,7 @@ A _retained_ parser can then be defined using...
* * *
```c
mpc_parser_t* mpc_define(mpc_parser_t* p, mpc_parser_t* a);
mpc_parser_t *mpc_define(mpc_parser_t *p, mpc_parser_t *a);
```
This assigns the contents of parser `a` to `p`, and deletes `a`. With this technique parsers can now reference each other, as well as themselves, without trouble.
@@ -462,7 +467,7 @@ This assigns the contents of parser `a` to `p`, and deletes `a`. With this techn
* * *
```c
mpc_parser_t* mpc_undefine(mpc_parser_t* p);
mpc_parser_t *mpc_undefine(mpc_parser_t *p);
```
A final step is required. Parsers that reference each other must all be undefined before they are deleted. It is important to do any undefining before deletion. The reason for this is that to delete a parser it must look at each sub-parser that is used by it. If any of these have already been deleted a segfault is unavoidable - even if they were retained beforehand.
@@ -482,57 +487,57 @@ Common Parsers
A number of common parsers are included.
* `mpc_parser_t* mpc_soi(void);` Matches only the start of input, returns `NULL`
* `mpc_parser_t* mpc_eoi(void);` Matches only the end of input, returns `NULL`
* `mpc_parser_t* mpc_space(void);` Matches any whitespace character (" \f\n\r\t\v")
* `mpc_parser_t* mpc_spaces(void);` Matches zero or more whitespace characters
* `mpc_parser_t* mpc_whitespace(void);` Matches spaces and frees the result, returns `NULL`
* `mpc_parser_t* mpc_newline(void);` Matches `'\n'`
* `mpc_parser_t* mpc_tab(void);` Matches `'\t'`
* `mpc_parser_t* mpc_escape(void);` Matches a backslash followed by any character
* `mpc_parser_t* mpc_digit(void);` Matches any character in the range `'0'` - `'9'`
* `mpc_parser_t* mpc_hexdigit(void);` Matches any character in the range `'0'` - `'9'` as well as `'A'` - `'F'` and `'a'` - `'f'`
* `mpc_parser_t* mpc_octdigit(void);` Matches any character in the range `'0'` - `'7'`
* `mpc_parser_t* mpc_digits(void);` Matches one or more digit
* `mpc_parser_t* mpc_hexdigits(void);` Matches one or more hexdigit
* `mpc_parser_t* mpc_octdigits(void);` Matches one or more octdigit
* `mpc_parser_t* mpc_lower(void);` Matches and lower case character
* `mpc_parser_t* mpc_upper(void);` Matches any upper case character
* `mpc_parser_t* mpc_alpha(void);` Matches and alphabet character
* `mpc_parser_t* mpc_underscore(void);` Matches `'_'`
* `mpc_parser_t* mpc_alphanum(void);` Matches any alphabet character, underscore or digit
* `mpc_parser_t* mpc_int(void);` Matches digits and returns an `int*`
* `mpc_parser_t* mpc_hex(void);` Matches hexdigits and returns an `int*`
* `mpc_parser_t* mpc_oct(void);` Matches octdigits and returns an `int*`
* `mpc_parser_t* mpc_number(void);` Matches `mpc_int`, `mpc_hex` or `mpc_oct`
* `mpc_parser_t* mpc_real(void);` Matches some floating point number as a string
* `mpc_parser_t* mpc_float(void);` Matches some floating point number and returns a `float*`
* `mpc_parser_t* mpc_char_lit(void);` Matches some character literal surrounded by `'`
* `mpc_parser_t* mpc_string_lit(void);` Matches some string literal surrounded by `"`
* `mpc_parser_t* mpc_regex_lit(void);` Matches some regex literal surrounded by `/`
* `mpc_parser_t* mpc_ident(void);` Matches a C style identifier
* `mpc_soi(void);` Matches only the start of input, returns `NULL`
* `mpc_eoi(void);` Matches only the end of input, returns `NULL`
* `mpc_space(void);` Matches any whitespace character (" \f\n\r\t\v")
* `mpc_spaces(void);` Matches zero or more whitespace characters
* `mpc_whitespace(void);` Matches spaces and frees the result, returns `NULL`
* `mpc_newline(void);` Matches `'\n'`
* `mpc_tab(void);` Matches `'\t'`
* `mpc_escape(void);` Matches a backslash followed by any character
* `mpc_digit(void);` Matches any character in the range `'0'` - `'9'`
* `mpc_hexdigit(void);` Matches any character in the range `'0'` - `'9'` as well as `'A'` - `'F'` and `'a'` - `'f'`
* `mpc_octdigit(void);` Matches any character in the range `'0'` - `'7'`
* `mpc_digits(void);` Matches one or more digit
* `mpc_hexdigits(void);` Matches one or more hexdigit
* `mpc_octdigits(void);` Matches one or more octdigit
* `mpc_lower(void);` Matches and lower case character
* `mpc_upper(void);` Matches any upper case character
* `mpc_alpha(void);` Matches and alphabet character
* `mpc_underscore(void);` Matches `'_'`
* `mpc_alphanum(void);` Matches any alphabet character, underscore or digit
* `mpc_int(void);` Matches digits and returns an `int*`
* `mpc_hex(void);` Matches hexdigits and returns an `int*`
* `mpc_oct(void);` Matches octdigits and returns an `int*`
* `mpc_number(void);` Matches `mpc_int`, `mpc_hex` or `mpc_oct`
* `mpc_real(void);` Matches some floating point number as a string
* `mpc_float(void);` Matches some floating point number and returns a `float*`
* `mpc_char_lit(void);` Matches some character literal surrounded by `'`
* `mpc_string_lit(void);` Matches some string literal surrounded by `"`
* `mpc_regex_lit(void);` Matches some regex literal surrounded by `/`
* `mpc_ident(void);` Matches a C style identifier
Useful Parsers
--------------
* `mpc_parser_t* mpc_start(mpc_parser_t* a);` Matches the start of input followed by `a`
* `mpc_parser_t* mpc_end(mpc_parser_t* a, mpc_dtor_t da);` Matches `a` followed by the end of input
* `mpc_parser_t* mpc_enclose(mpc_parser_t* a, mpc_dtor_t da);` Matches the start of input, `a`, and the end of input
* `mpc_parser_t* mpc_strip(mpc_parser_t* a);` Matches `a` striping any surrounding whitespace
* `mpc_parser_t* mpc_tok(mpc_parser_t* a);` Matches `a` and strips any trailing whitespace
* `mpc_parser_t* mpc_sym(const char* s);` Matches string `s` and strips any trailing whitespace
* `mpc_parser_t* mpc_total(mpc_parser_t* a, mpc_dtor_t da);` Matches the whitespace stripped `a`, enclosed in the start and end of input
* `mpc_parser_t* mpc_between(mpc_parser_t* a, mpc_dtor_t ad, const char* o, const char* c);` Matches `a` between strings `o` and `c`
* `mpc_parser_t* mpc_parens(mpc_parser_t* a, mpc_dtor_t ad);` Matches `a` between `"("` and `")"`
* `mpc_parser_t* mpc_braces(mpc_parser_t* a, mpc_dtor_t ad);` Matches `a` between `"<"` and `">"`
* `mpc_parser_t* mpc_brackets(mpc_parser_t* a, mpc_dtor_t ad);` Matches `a` between `"{"` and `"}"`
* `mpc_parser_t* mpc_squares(mpc_parser_t* a, mpc_dtor_t ad);` Matches `a` between `"["` and `"]"`
* `mpc_parser_t* mpc_tok_between(mpc_parser_t* a, mpc_dtor_t ad, const char* o, const char* c);` Matches `a` between `o` and `c`, where `o` and `c` have their trailing whitespace striped.
* `mpc_parser_t* mpc_tok_parens(mpc_parser_t* a, mpc_dtor_t ad);` Matches `a` between trailing whitespace stripped `"("` and `")"`
* `mpc_parser_t* mpc_tok_braces(mpc_parser_t* a, mpc_dtor_t ad);` Matches `a` between trailing whitespace stripped `"<"` and `">"`
* `mpc_parser_t* mpc_tok_brackets(mpc_parser_t* a, mpc_dtor_t ad);` Matches `a` between trailing whitespace stripped `"{"` and `"}"`
* `mpc_parser_t* mpc_tok_squares(mpc_parser_t* a, mpc_dtor_t ad);` Matches `a` between trailing whitespace stripped `"["` and `"]"`
* `mpc_start(mpc_parser_t *a);` Matches the start of input followed by `a`
* `mpc_end(mpc_parser_t *a, mpc_dtor_t da);` Matches `a` followed by the end of input
* `mpc_enclose(mpc_parser_t *a, mpc_dtor_t da);` Matches the start of input, `a`, and the end of input
* `mpc_strip(mpc_parser_t *a);` Matches `a` striping any surrounding whitespace
* `mpc_tok(mpc_parser_t *a);` Matches `a` and strips any trailing whitespace
* `mpc_sym(const char* s);` Matches string `s` and strips any trailing whitespace
* `mpc_total(mpc_parser_t *a, mpc_dtor_t da);` Matches the whitespace stripped `a`, enclosed in the start and end of input
* `mpc_between(mpc_parser_t *a, mpc_dtor_t ad, const char* o, const char* c);` Matches `a` between strings `o` and `c`
* `mpc_parens(mpc_parser_t *a, mpc_dtor_t ad);` Matches `a` between `"("` and `")"`
* `mpc_braces(mpc_parser_t *a, mpc_dtor_t ad);` Matches `a` between `"<"` and `">"`
* `mpc_brackets(mpc_parser_t *a, mpc_dtor_t ad);` Matches `a` between `"{"` and `"}"`
* `mpc_squares(mpc_parser_t *a, mpc_dtor_t ad);` Matches `a` between `"["` and `"]"`
* `mpc_tok_between(mpc_parser_t *a, mpc_dtor_t ad, const char* o, const char* c);` Matches `a` between `o` and `c`, where `o` and `c` have their trailing whitespace striped.
* `mpc_tok_parens(mpc_parser_t *a, mpc_dtor_t ad);` Matches `a` between trailing whitespace stripped `"("` and `")"`
* `mpc_tok_braces(mpc_parser_t *a, mpc_dtor_t ad);` Matches `a` between trailing whitespace stripped `"<"` and `">"`
* `mpc_tok_brackets(mpc_parser_t *a, mpc_dtor_t ad);` Matches `a` between trailing whitespace stripped `"{"` and `"}"`
* `mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad);` Matches `a` between trailing whitespace stripped `"["` and `"]"`
Fold Functions
@@ -590,10 +595,10 @@ And then we use this to specify a basic grammar, which folds together any result
```c
int parse_maths(char* input) {
mpc_parser_t* Expr = mpc_new("expr");
mpc_parser_t* Factor = mpc_new("factor");
mpc_parser_t* Term = mpc_new("term");
mpc_parser_t* Maths = mpc_new("maths");
mpc_parser_t *Expr = mpc_new("expr");
mpc_parser_t *Factor = mpc_new("factor");
mpc_parser_t *Term = mpc_new("term");
mpc_parser_t *Maths = mpc_new("maths");
mpc_define(Expr, mpc_or(2,
mpc_and(3, mpcf_maths, Factor, mpc_oneof("*/"), Factor, free, free),
@@ -632,7 +637,7 @@ Even with all that has been shown above, specifying parts of text can be a tedio
* * *
```c
mpc_parser_t* mpc_re(const char* re);
mpc_parser_t *mpc_re(const char* re);
```
This returns a parser that will attempt to match the given regular expression pattern, and return the matched string on success. It does not have support for groups and match objects, but should be sufficient for simple tasks.
@@ -670,7 +675,7 @@ Like with the regular expressions, this user input is parsed by existing parts o
* * *
```c
mpc_parser_t* mpca_grammar(const char* grammar, ...);
mpc_parser_t *mpca_grammar(const char* grammar, ...);
```
This takes in some single right hand side of a rule, as well as a list of any of the parsers it refers to, and outputs a parser that does exactly what is specified by the rule.
@@ -694,7 +699,7 @@ This reads in the contents of file `f` and inputs it into `mpca_lang`.
* * *
```c
mpc_err_t* mpca_lang_filename(const char* filename, ...);
mpc_err_t* mpca_lang_contents(const char* filename, ...);
```
This opens and reads in the contents of the file given by `filename` and passes it to `mpca_lang`.