From 827c189e562757839998e3445642b48149a01b7c Mon Sep 17 00:00:00 2001 From: Daniel Holden Date: Thu, 26 Sep 2013 14:28:01 +0100 Subject: [PATCH] Readme tweaks --- README.md | 56 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 99e160b..246d4b9 100644 --- a/README.md +++ b/README.md @@ -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 '(' @@ -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");