Readme tweaks

This commit is contained in:
Daniel Holden
2013-09-26 14:28:01 +01:00
parent 8cc7aa6a0d
commit 827c189e56

View File

@@ -9,7 +9,7 @@ Using _mpc_ might be of interest to you if you are...
* Building a new data format
* Parsing an existing data format
* 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
@@ -25,7 +25,7 @@ Features
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:
@@ -38,9 +38,9 @@ The main advantages of _mpc_ over this are:
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
#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>
<value>
<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.
* * *
```c
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.
* * *
```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);
@@ -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`.
* * *
```c
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);
@@ -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`.
* * *
```c
mpc_parser_t* mpc_maybe(mpc_parser_t* a);
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`).
* * *
```c
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);
@@ -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.
* * *
```c
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`.
* * *
```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_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`.
* * *
```c
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.
* * *
```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_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`.
* * *
```c
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'`.
* * *
```c
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.
### Destructor Function
```c
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
typedef mpc_val_t*(*mpc_apply_t)(mpc_val_t*);
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
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
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
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
-------
@@ -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.
```
```c
char* parse_ident(char* input) {
mpc_parser_t* alpha = mpc_oneof("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");