Readme tweaks
This commit is contained in:
56
README.md
56
README.md
@@ -9,7 +9,7 @@ Using _mpc_ might be of interest to you if you are...
|
|||||||
* Building a new data format
|
* Building a new data format
|
||||||
* Parsing an existing data format
|
* Parsing an existing data format
|
||||||
* Embedding a Domain Specific Language
|
* Embedding a Domain Specific Language
|
||||||
* (http://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule)[Adding an ad-hoc embedded Lisp to your C program]
|
* [Adding an ad-hoc embedded Lisp to your C program](http://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule)
|
||||||
|
|
||||||
|
|
||||||
Features
|
Features
|
||||||
@@ -25,7 +25,7 @@ Features
|
|||||||
Alternatives
|
Alternatives
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The current main alternative C based parser combinator is a branch of (https://github.com/wbhart/Cesium3/tree/combinators)[Cesium3].
|
The current main alternative C based parser combinator is a branch of [Cesium3](https://github.com/wbhart/Cesium3/tree/combinators).
|
||||||
|
|
||||||
The main advantages of _mpc_ over this are:
|
The main advantages of _mpc_ over this are:
|
||||||
|
|
||||||
@@ -38,9 +38,9 @@ The main advantages of _mpc_ over this are:
|
|||||||
View From the Top
|
View From the Top
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
In this example I specify a grammar for a basic maths language and parse a string from it.
|
In this example I specify a grammar for a basic maths language.
|
||||||
|
|
||||||
The output is an instance of the included `mpc_ast_t` type.
|
The output from the parse is an instance of the included `mpc_ast_t` type.
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#include "mpc.h"
|
#include "mpc.h"
|
||||||
@@ -69,9 +69,9 @@ mpc_ast_t* parse_maths(const char* input) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Then the output for the parse of an expression `(4 * 2 * 11 + 2) + 5` would look something like this
|
The output for the parse of an expression like `(4 * 2 * 11 + 2) + 5` would look something like this
|
||||||
|
|
||||||
```xml
|
```c
|
||||||
<root>
|
<root>
|
||||||
<value>
|
<value>
|
||||||
<char> '('
|
<char> '('
|
||||||
@@ -149,6 +149,8 @@ A second annoyance in C is that of manual memory management. Some parsers might
|
|||||||
|
|
||||||
Here are the main combinators and how to use then.
|
Here are the main combinators and how to use then.
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```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);
|
||||||
```
|
```
|
||||||
@@ -165,6 +167,8 @@ might report `error: expected '0' or '1' at 'x'`, while
|
|||||||
|
|
||||||
will report `error: expected binary digit at 'x'` which in some circumstances can drastically improve readability of error messages.
|
will report `error: expected binary digit at 'x'` which in some circumstances can drastically improve readability of error messages.
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```c
|
||||||
mpc_parser_t* mpc_apply(mpc_parser_t* a, mpc_apply_t f);
|
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_to(mpc_parser_t* a, mpc_apply_to_t f, void* x);
|
||||||
@@ -172,6 +176,8 @@ mpc_parser_t* mpc_apply_to(mpc_parser_t* a, mpc_apply_to_t f, void* x);
|
|||||||
|
|
||||||
Applies function `f` (optionality taking extra input `x`) to the result of parser `a`.
|
Applies function `f` (optionality taking extra input `x`) to the result of parser `a`.
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```c
|
||||||
mpc_parser_t* mpc_not(mpc_parser_t* a, mpc_dtor_t da);
|
mpc_parser_t* mpc_not(mpc_parser_t* a, mpc_dtor_t da);
|
||||||
mpc_parser_t* mpc_not_else(mpc_parser_t* a, mpc_dtor_t da, mpc_lift_t lf);
|
mpc_parser_t* mpc_not_else(mpc_parser_t* a, mpc_dtor_t da, mpc_lift_t lf);
|
||||||
@@ -181,6 +187,8 @@ Returns a parser with the following behaviour. If parser `a` succeeds, the outpu
|
|||||||
|
|
||||||
Destructor `da` is used to destroy the result of `a`.
|
Destructor `da` is used to destroy the result of `a`.
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```c
|
||||||
mpc_parser_t* mpc_maybe(mpc_parser_t* a);
|
mpc_parser_t* mpc_maybe(mpc_parser_t* a);
|
||||||
mpc_parser_t* mpc_maybe_else(mpc_parser_t* a, mpc_lift_t lf);
|
mpc_parser_t* mpc_maybe_else(mpc_parser_t* a, mpc_lift_t lf);
|
||||||
@@ -188,6 +196,8 @@ mpc_parser_t* mpc_maybe_else(mpc_parser_t* a, mpc_lift_t lf);
|
|||||||
|
|
||||||
Attempts to parser `a`. If this fails then succeeds and returns `NULL` (or the result of `lf`).
|
Attempts to parser `a`. If this fails then succeeds and returns `NULL` (or the result of `lf`).
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```c
|
||||||
mpc_parser_t* mpc_many(mpc_parser_t* a, mpc_fold_t f);
|
mpc_parser_t* mpc_many(mpc_parser_t* a, mpc_fold_t f);
|
||||||
mpc_parser_t* mpc_many_else(mpc_parser_t* a, mpc_fold_t f, mpc_lift_t lf);
|
mpc_parser_t* mpc_many_else(mpc_parser_t* a, mpc_fold_t f, mpc_lift_t lf);
|
||||||
@@ -197,12 +207,16 @@ Attempts to parse zero or more `a`. If zero instances are found then succeeds an
|
|||||||
|
|
||||||
If more than zero instances are found, results of `a` are combined using fold function `f`. See the _Function Types_ section for more details.
|
If more than zero instances are found, results of `a` are combined using fold function `f`. See the _Function Types_ section for more details.
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```c
|
||||||
mpc_parser_t* mpc_many1(mpc_parser_t* a, mpc_fold_t f);
|
mpc_parser_t* mpc_many1(mpc_parser_t* a, mpc_fold_t f);
|
||||||
```
|
```
|
||||||
|
|
||||||
Attempts to parse one or more `a`. Results are combined with fold function `f`.
|
Attempts to parse one or more `a`. Results are combined with fold function `f`.
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```c
|
||||||
mpc_parser_t* mpc_count(mpc_parser_t* a, mpc_dtor_t da, mpc_fold_t f, int n);
|
mpc_parser_t* mpc_count(mpc_parser_t* a, mpc_dtor_t da, mpc_fold_t f, int n);
|
||||||
mpc_parser_t* mpc_count_else(mpc_parser_t* a, mpc_dtor_t da, mpc_fold_t f, int n, mpc_lift_t lf);
|
mpc_parser_t* mpc_count_else(mpc_parser_t* a, mpc_dtor_t da, mpc_fold_t f, int n, mpc_lift_t lf);
|
||||||
@@ -212,12 +226,16 @@ Attempts to parse exactly `n` of `a`. If it fails the result output by the fold
|
|||||||
|
|
||||||
Results of `a` are combined using fold function `f`.
|
Results of `a` are combined using fold function `f`.
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```c
|
||||||
mpc_parser_t* mpc_else(mpc_parser_t* a, mpc_parser_t* b);
|
mpc_parser_t* mpc_else(mpc_parser_t* a, mpc_parser_t* b);
|
||||||
```
|
```
|
||||||
|
|
||||||
Attempts to parse `a` and if fails attempts to parse `b`. If both fail, returns an error.
|
Attempts to parse `a` and if fails attempts to parse `b`. If both fail, returns an error.
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```c
|
||||||
mpc_parser_t* mpc_also(mpc_parser_t* a, mpc_parser_t* b, mpc_dtor_t da, mpc_fold_t f);
|
mpc_parser_t* mpc_also(mpc_parser_t* a, mpc_parser_t* b, mpc_dtor_t da, mpc_fold_t f);
|
||||||
mpc_parser_t* mpc_bind(mpc_parser_t* a, mpc_parser_t* b, mpc_dtor_t da, mpc_fold_t f);
|
mpc_parser_t* mpc_bind(mpc_parser_t* a, mpc_parser_t* b, mpc_dtor_t da, mpc_fold_t f);
|
||||||
@@ -225,6 +243,8 @@ mpc_parser_t* mpc_bind(mpc_parser_t* a, mpc_parser_t* b, mpc_dtor_t da, mpc_fold
|
|||||||
|
|
||||||
Attempts to parse `a` and then attempts to parse `b`. If `b` fails it destructs the result of `a` using `da`. If both succeed it returns the result of `a` and `b` combined using the fold function `f`.
|
Attempts to parse `a` and then attempts to parse `b`. If `b` fails it destructs the result of `a` using `da`. If both succeed it returns the result of `a` and `b` combined using the fold function `f`.
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```c
|
||||||
mpc_parser_t* mpc_or(int n, ...);
|
mpc_parser_t* mpc_or(int n, ...);
|
||||||
```
|
```
|
||||||
@@ -233,6 +253,8 @@ Attempts to parse `n` parsers in sequence, returning the first one that succeeds
|
|||||||
|
|
||||||
For example: `mpc_or(3, mpc_char('a'), mpc_char('b'), mpc_char('c'))` would attempt to match either an `'a'` or a `'b'` or a `'c'`.
|
For example: `mpc_or(3, mpc_char('a'), mpc_char('b'), mpc_char('c'))` would attempt to match either an `'a'` or a `'b'` or a `'c'`.
|
||||||
|
|
||||||
|
* * *
|
||||||
|
|
||||||
```c
|
```c
|
||||||
mpc_parser_t* mpc_and(int n, mpc_afold_t f, ...);
|
mpc_parser_t* mpc_and(int n, mpc_afold_t f, ...);
|
||||||
```
|
```
|
||||||
@@ -247,36 +269,46 @@ Function Types
|
|||||||
|
|
||||||
The combinator functions take a number of special function types as function pointers. Here is a short explanation of those types are how they are expected to behave.
|
The combinator functions take a number of special function types as function pointers. Here is a short explanation of those types are how they are expected to behave.
|
||||||
|
|
||||||
|
### Destructor Function
|
||||||
|
|
||||||
```c
|
```c
|
||||||
typedef void(*mpc_dtor_t)(mpc_val_t*);
|
typedef void(*mpc_dtor_t)(mpc_val_t*);
|
||||||
```
|
```
|
||||||
|
|
||||||
Destructor function. Given some pointer to a data value it will ensure the memory it points to is freed correctly.
|
Given some pointer to a data value it will ensure the memory it points to is freed correctly.
|
||||||
|
|
||||||
|
### Application function
|
||||||
|
|
||||||
```c
|
```c
|
||||||
typedef mpc_val_t*(*mpc_apply_t)(mpc_val_t*);
|
typedef mpc_val_t*(*mpc_apply_t)(mpc_val_t*);
|
||||||
typedef mpc_val_t*(*mpc_apply_to_t)(mpc_val_t*,void*);
|
typedef mpc_val_t*(*mpc_apply_to_t)(mpc_val_t*,void*);
|
||||||
```
|
```
|
||||||
|
|
||||||
Application function. This takes in some pointer to data and outputs some new or modified pointer to data, ensuring to free and old data no longer required. The `apply_to` variation takes in an extra pointer to some data such as state of the system.
|
This takes in some pointer to data and outputs some new or modified pointer to data, ensuring to free and old data no longer required. The `apply_to` variation takes in an extra pointer to some data such as state of the system.
|
||||||
|
|
||||||
|
### Fold function
|
||||||
|
|
||||||
```c
|
```c
|
||||||
typedef mpc_val_t*(*mpc_fold_t)(mpc_val_t*,mpc_val_t*);
|
typedef mpc_val_t*(*mpc_fold_t)(mpc_val_t*,mpc_val_t*);
|
||||||
```
|
```
|
||||||
|
|
||||||
Fold function. This takes two pointers to data and must output some new combined pointer to data, ensuring to free and old data no longer required. When used with the `many`, `many1` and `count` functions this initially takes in `NULL` for it's first argument and following that takes in for it's first argument whatever was previously returned by the function itself. In this way users have a chance to build some initial data structure before populating it with whatever is passed as the second argument.
|
This takes two pointers to data and must output some new combined pointer to data, ensuring to free and old data no longer required. When used with the `many`, `many1` and `count` functions this initially takes in `NULL` for it's first argument and following that takes in for it's first argument whatever was previously returned by the function itself. In this way users have a chance to build some initial data structure before populating it with whatever is passed as the second argument.
|
||||||
|
|
||||||
|
### AFold Function
|
||||||
|
|
||||||
```c
|
```c
|
||||||
typedef mpc_val_t*(*mpc_afold_t)(int,mpc_val_t**);
|
typedef mpc_val_t*(*mpc_afold_t)(int,mpc_val_t**);
|
||||||
```
|
```
|
||||||
|
|
||||||
AFold Function. Similar to the above but it is passed in a list of pointers to data values which must all be folded together and output as a new single data value.
|
Similar to the above but it is passed in a list of pointers to data values which must all be folded together and output as a new single data value.
|
||||||
|
|
||||||
|
### Lift Function
|
||||||
|
|
||||||
```c
|
```c
|
||||||
typedef mpc_val_t*(*mpc_lift_t)(void);
|
typedef mpc_val_t*(*mpc_lift_t)(void);
|
||||||
```
|
```
|
||||||
|
|
||||||
Lift Function. This function returns some data value when called. It can be used to create _empty_ versions of data types when certain combinators have no known default value to return.
|
This function returns some data value when called. It can be used to create _empty_ versions of data types when certain combinators have no known default value to return.
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
@@ -302,7 +334,7 @@ mpc_val_t* parse_fold_string(mpc_val_t* x, mpc_val_t* y) {
|
|||||||
|
|
||||||
Then we can actually specify the grammar.
|
Then we can actually specify the grammar.
|
||||||
|
|
||||||
```
|
```c
|
||||||
char* parse_ident(char* input) {
|
char* parse_ident(char* input) {
|
||||||
|
|
||||||
mpc_parser_t* alpha = mpc_oneof("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
mpc_parser_t* alpha = mpc_oneof("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||||
|
Reference in New Issue
Block a user