Table of Contents
- Core API
-
- CPARSEC2 core APIs
- Exception handling API for C.
- Container classes
-
- Type of Containers
- Supporting concrete
List(T)types - Iteration API for
List(T) - Supporting concrete
Buff(T)types - List builder API for
Buff(T)
- Parser classes
-
- Type of Parsers
- Supporting concrete
PARSER(T)types
- Built-in Parsers, Parser generators, and Parser combinators
-
- Built-in Parsers
- Built-in Parser-generators
- Built-in GENERIC Parser-combinators
- Building block of Parser-class
-
- Declares/Defines new PARSER(T) class
- Construct an instance of PARSER(T)
- Apply an instance of PARSER(T) to a text
- Building block of Parser-combinators
-
- Declares/Defines new Parser-combinators
- PARSER_CAST(expr)
- GENERIC_METHOD(expr, C, F, …)
- GENERIC_P(expr, F, …)
- FOREACH(F, …)
- TYPESET
- Extends CPARSEC2 library for user defined types
-
- CPARSEC2_USER_TYPESET
- CPARSEC2_DEFINE_USER_TYPESET()
- cparsec2_init()
-
Initialize cparsec2 library.
This must be called once at first. - cparsec2_end()
-
Clean up cparsec2 library. (deallocate all allocated memory)
During after calling this API and before callingcparsec2_init(), calling any other cparsec2 API and values returned from them are invalid (access to them will be undefined behavior). - Source_new(input)
-
Constructs a
Sourceobject from the giveninput.- input
- a
const char*,FILE*, orSource. - return
- a new
Sourceobject, orinputifinputwas aSource.
- parse(p, src, ctx)
-
Apply parser
pto text provided from theSourceobjectsrc, and return result (such aschar,const char *). If an error occurred, it is thrown as exception throughctx. (see also Exception handling)- p
- a parser of
PARSER(T)type such asPARSER(Char), etc. - src
- a
Sourceobject. - ctx
- a potinter to
Ctxobject. - return
- an object of
RETURN_TYPE(PARSER(T))type. For example,- a
charifpwas aPARSER(Char), - a
const char*ifpwas aPARSER(String), - a
intifpwas aPARSER(Int), NONEifpwas aPARSER(None).
- a
- parseTest(p, text)
-
Apply parser
ptotextand print result to standard output.
Returntrueif passed,falseif failed.- p
- a parser of
PARSER(T)type such asPARSER(Char), etc. - text
- a
const char*. (null-terminated char sequence; i.e. string in C) - return
trueorfalse.
- PARSE_TEST(p, text)
-
Same as
parseTestand also printp text. (for debug purpose)
Returntrueif passed,falseif failed.- p
- a parser of
PARSER(T)type such asPARSER(Char), etc. - text
- a
const char*. (null-terminated char sequence; i.e. string in C) - return
trueorfalse.
- runParser(p, input)
-
Apply parser
ptoinput.inputis aconst char*,FILE*, orSource.
Returns aParseResult(T).- p
- a parser of
PARSER(T)type such asPARSER(Char), etc. - input
- a
const char*,FILE*, orSource. - return
- an object of
ParseResult(T)type such asParseResult(Char), etc.
- Ctx
- Type of context for exception handling.
- TRY(ctx) {…} else {…}
-
Exception handling macro. (C++ or Java like
try {...} catch {...}clause) - cthrow(ctx, msg)
-
Throw a string
msgas an exception.
Example:
Ctx ctx;
TRY(&ctx) { /* try */
// ...
cthrow(&ctx, "something wrong!"); /* throw "something wrong!" */
// ...
}
else { /* catch */
printf("error:%s\n", ctx.msg); /* -> "error: something wrong!" */
}- List(T)
-
Generic type of a list ; container of object sequence.
NOTE : To construct aList(T)object, useBuff(T). - ELEMENT_TYPE(List(T))
-
Element type of
List(T).
- Buff(T)
- Generic type of a list builder ; variadic buffer of object sequence for building a list.
- ELEMENT_TYPE(Buff(T))
-
Element type of
Buff(T).
- List(Char)
-
A type of a list container whose element type is
const char.
(i.e.ELEMENT_TYPE(List(Char))isconst char.) - List(String)
-
A type of a list container whose element type is
const char*.
(i.e.ELEMENT_TYPE(List(String))isconst char*.) - List(Int)
-
A type of a list container whose element type is
int.
(i.e.ELEMENT_TYPE(List(Int))isint.) - List(None)
-
A type of a list container whose element type is
None.
(i.e.ELEMENT_TYPE(List(None))isNone.) - List(Ptr)
-
A type of a list container whose element type is
void*.
(i.e.ELEMENT_TYPE(List(Ptr))isvoid*.)
NOTE : List(Char) is same as const char* (i.e. string in C)
The below is an experimental:
- List(Node)
-
A type of a list container whose element type is
Node.
(i.e.ELEMENT_TYPE(List(Node))isNode.)
To iterate elements contained in a List(T) object, use the following APIs.
- ELEMENT_TYPE(List(T))* list_begin(List(T) xs)
- Retunrs an iterator, which points to the 1st element of the list. (inclusive)
- ELEMENT_TYPE(List(T))* list_end(List(T) xs)
- Returns an iterator, which points to the next of the last element. (out of range)
- int list_length(List(T) xs)
-
Returns the number of elements.
NOTE : list_begin(xs) + list_length(xs) == list_end(xs)
For example:
/* a null-terminated char sequence is also a List(Char) */
List(Char) xs = "abcdefg";
const char* itr = list_begin(xs);
const char* end = list_end(xs);
while (itr != end) {
printf("%c\n", *itr);
itr++;
}- Buff(Char)
-
A type of a list-builder whose element type is
char.
(i.e.ELEMENT_TYPE(Buff(Char))ischar.) - Buff(String)
-
A type of a list-builder whose element type is
const char*.
(i.e.ELEMENT_TYPE(Buff(String))isconst char*.) - Buff(Int)
-
A type of a list-builder whose element type is
int.
(i.e.ELEMENT_TYPE(Buff(Int))isint.) - Buff(None)
-
A type of a list-builder whose element type is
None.
(i.e.ELEMENT_TYPE(Buff(None))isNone.) - Buff(Ptr)
-
A type of a list-builder whose element type is
void*.
(i.e.ELEMENT_TYPE(Buff(Ptr))isvoid*.)
The below is an experimental:
- Buff(Node)
-
A type of a list-builder whose element type is
Node.
(i.e.ELEMENT_TYPE(Buff(Node))isNode.)
To build a List(T) object, use the following APIs:
- void buff_push(Buff(T)* buf, ELEMENT_TYPE(Buff(T)) x)
-
Adds an element
xto the last ofbuf. - void buff_append(Buff(T)* buf, List(T) xs)
-
Adds elements in the
xsto the last ofbuf. - List(T) buff_finish(Buff(T)* buf)
-
Creates a
List(T)object and clear contents ofbuf.
For example:
/* A Buff(T) object must be initialized with {0} at first. */
Buff(Int) buf = {0};
for (int i = 0; i < 10; ++i) {
buff_push(&buf, i);
}
List(Int) xs = buf_finish(&buf);
int* itr = list_begin(xs);
int* end = list_end(xs);
while (itr != end) {
printf("%d", *itr++); /* -> "0123456789" */
}
printf("\n");Additionaly, Buff(Char) has also the following APIs:
- void buff_printf(Buff(Char)* buf, const char* format, …)
-
Appends a
printf()-like formatted string to the last ofbuf. - void buff_vprintf(Buff(Char)* buf, const char* format, va_list ap)
-
Equivalent to the
buff_printf()except that it is called with ava_listinstead of variable number of arguments. Seestdarg(3).
For example:
const char* name = "Bob";
int year = 2000;
int month = 4;
int day = 10;
Buff(Char) buf = {0};
buff_printf(&buf, "name: %s, ", name);
buff_printf(&buf, "birthday: %4d-%02d-%02d", year, month, day);
const char* s = buff_finish(&buf);
// -> s = "name: Bob, birthday: 2000-04-10"- PARSER(T)
-
Generic type of parser.
When a parser applied to a text (char sequence), the parser reads the given text and returns a corresponding value as the parsed result. - RETURN_TYPE(PARSER(T))
-
Type of a value to be returned by a parser of
PARSER(T)type.
- PARSER(Char)
-
A parser of
PARSER(Char)type returns acharvalue when it is applied.
(i.e.RETURN_TYPE(PARSER(Char))ischar.) - PARSER(String)
-
A parser of
PARSER(String)type returns aconst char*value when it is applied.
(i.e.RETURN_TYPE(PARSER(String))isconst char*.) - PARSER(Int)
-
A parser of
PARSER(Int)type returns aintvalue when it is applied.
(i.e.RETURN_TYPE(PARSER(Int))isint.) - PARSER(None)
-
A parser of
PARSER(None)type returnsNONEwhen it is applied.
(i.e.RETURN_TYPE(PARSER(None))isNone.)
- PARSER(List(Char))
-
A parser of
PARSER(List(Char))type returns aList(Char)value when it is applied.
(i.e.RETURN_TYPE(PARSER(List(Char)))isList(Char).)- NOTE :
PARSER(List(Char))is same asPARSER(String), andList(Char)is same asconst char*.
- NOTE :
- PARSER(List(String))
-
A parser of
PARSER(List(String))type returns aList(String)value when it is applied.
(i.e.RETURN_TYPE(PARSER(List(String)))isList(String).) - PARSER(List(Int))
-
A parser of
PARSER(List(Int))type returns aList(Int)value when it is applied.
(i.e.RETURN_TYPE(PARSER(List(Int)))isList(Int).) - PARSER(List(None))
-
A parser of
PARSER(List(None))type returns aList(None)value when it is applied.
(i.e.RETURN_TYPE(PARSER(List(None)))isList(None).)
The below is an experimental:
- PARSER(Node)
-
A parser of
PARSER(Node)type returns aNodevalue when it is applied.
(i.e.RETURN_TYPE(PARSER(Node))isNode.) - PARSER(List(Node))
-
A parser of
PARSER(List(Node))type returns aList(Node)value when it is applied.
(i.e.RETURN_TYPE(PARSER(List(Node)))isList(Node).)
- parser
-
A functional object for parsing input stream.
- When a parser was applied to an input stream:
- it takes zero or more tokens (e.g. sequence of chars) from the input,
- then execute something pattern match, and
- returns a corresponding value if succeeded.
- otherwise causes an error by throwing an exception.
- To apply a parser, use one of the following APIs (see also Core API):
parse(parser, src, ex)parseTest(parser, text)PARSE_TEST(parser, text)runParser(parser, input)
- When a parser was applied to an input stream:
- parser generator
-
A factory method (constructor function) for creating a parser.
- A parser generator takes one or more arguments for creating a parameterized parser.
- Typically the given arguments are used as parameters for pattern match.
- parser combinator
-
A factory method (constructor function) for creating a composite parser.
- A parser combinator takes one or more parsers for creating a composite parser.
- It is used to create a complex parser by combinating one or more simple parsers.
The below table shows characteristics of built-in parsers, parser generators, and parser combinators:
- parser column shows built-in parsers, parser generators, or parser combinators
- other columns show resulting status of
parse(parser, src, ex).
It causes one of the following result:- eok (empty ok)
-
- parser succeeded without consuming any input.
- Returns a corresponding value explained in that column.
- eerr (empty error)
-
- parser failed without consuming any input.
- Throws an exception via
ex.
(annotated as error in that column)
- cok (consumed ok)
-
- parser succeeded after consumed some input from
src. - Returns a corresponding value explained in that column.
- parser succeeded after consumed some input from
- cerr (consumed error)
-
- parser failed after consumed some input from
src. - Throws an exception via
ex.
(annotated as error in that column)
- parser failed after consumed some input from
- NOTE : n/a (not applicable) means that such resulting status does not occur.
- NOTE :
NONEis a value of typeNone.- A parser of
PARSER(None)type returnsNONEvalue, when it succeeded. - Parser of
PARSER(None)type has no meaningful value should to be returned, so it returnsNONEinstead.
- A parser of
| parser | eok | eerr | cok | cerr |
|---|---|---|---|---|
| anyChar | n/a | error | a char | n/a |
| digit | n/a | error | a decimal digit | n/a |
| hexDigit | n/a | error | a hexadecimal digit | n/a |
| octDigit | n/a | error | an octal digit | n/a |
| lower | n/a | error | a lower-case alphabet | n/a |
| upper | n/a | error | a upper-case alphabet | n/a |
| alpha | n/a | error | an alphabet | n/a |
| alnum | n/a | error | an alphabet or a decimal digit | n/a |
| letter | n/a | error | ’_’ or a alphabet | n/a |
| newline | n/a | error | linefeed (LF) | n/a |
| crlf | n/a | error | linefeed (LF) | n/a |
| endOfLine | n/a | error | linefeed (LF) | n/a |
| endOfFile | NONE | error | n/a | n/a |
| tab | n/a | error | horizontal tab (TAB) | n/a |
| space | n/a | error | space (SPC) | n/a |
| spaces | NONE | n/a | NONE | n/a |
| number | n/a | error | an int | n/a |
| anyUtf8 | n/a | error | a UTF-8 character as string | n/a |
| char1(c) | n/a | error | char c | error |
| string1(s) | n/a | error | string s | error |
| utf8(s) | n/a | error | UTF-8 string s | error |
| oneOf(s) | n/a | error | a char included in s | error |
| noneOf(s) | n/a | error | a char not included in s | error |
| satisfy(pred) | n/a | error | c satisfing pred(c) == true | error |
| range(min, max) | n/a | error | c satisfing min <= c && c <= max | error |
| many(p) | empty list | n/a | N-elements list (N > 0) | error |
| many1(p) | n/a | error | N-elements list (N > 0) | error |
| seq(p1, …, pn) | N-elements list (N = n) | error | N-elements list (N = n) | error |
| cons(p, ps) | N-elements list (N > 0) | error | N-elements list (N > 0) | error |
| skip(p) | NONE | error | NONE | error |
| skip1st(p1, p2) | return value of p2 | error | return value of p2 | error |
| skip2nd(p1, p2) | return value of p1 | error | return value of p1 | error |
| token(p) | return value of p | error | return value of p | error |
| either(p1, p2) | return value of p1 or p2 | error | return value of p1 or p2 | error |
| tryp(p) | return value of p | error | return value of p | n/a |
- anyChar
- A PARSER(Char) which parse any one char
- digit
-
A PARSER(Char) which parse a digit (i.e.
0..9) - hexDigit
-
A PARSER(Char) which parse a hexadecimal digit (i.e.
0..9,a..f, andA..F) - octDigit
-
A PARSER(Char) which parse a octal digit (i.e.
0..7) - lower
-
A PARSER(Char) which parse a lower-case char (i.e.
a..z) - upper
-
A PARSER(Char) which parse a upper-case char (i.e.
A..Z) - alpha
-
A PARSER(Char) which parse an alphabet char (i.e.
a..z,A..Z) - alnum
-
A PARSER(Char) which parse a digit or an alphabet char (i.e.
0..9,a..z,A..Z) - letter
-
A PARSER(Char) which parse underscore or an alphabet char (i.e.
_,a..z,A..Z) - newline
- A PARSER(Char) which parse a newline character (i.e. LF)
- crlf
- A PARSER(Char) which parse a pair of CR and LF, and returns LF (i.e. CR LF → LF)
- endOfLine
- A PARSER(Char) which parse a LF or a CR-LF pair and returns LF.
- endOfFile
-
A PARSER(None) which succeeds if and only if it was the end of input, and
returns
NONE. - tab
- A PARSER(Char) which parse a TAB character.
- space
- A PARSER(Char) which parse a white-space (i.e. space, TAB, LF, CR)
- spaces
-
A PARSER(None) which parse zero or more white-spaces (i.e. space, TAB, LF,
CR), and returns
NONE. - number
-
A PARSER(Int) which parse one or more digits and skips trailing
white-spaces, then returns it as an
intvalue. - anyUtf8
- A PARSER(String) which parse any one UTF-8 character and returns it as a string.
- char1(c)
-
Create a PARSER(Char) which parse the char
c - string1(s)
-
Create a PARSER(String) which parse the string
s.- NOTE :
parse(string1(s), src, ex)succeeds:- if and only if the input from
srcwas starting withs. - otherwise fails without consuming any input.
- if and only if the input from
- NOTE :
- utf8(s)
-
Create a PARSER(String) which parse the UTF-8 string
s. - oneOf(cs)
-
Create a PARSER(Char) which parse a char
csatisfying it is contained in the stringcs. - noneOf(cs)
-
Create a PARSER(Char) which parse a char
csatisfying it is not contained in the stringcs. - satisfy(pred)
-
Create a PARSER(Char) which parse a char
csatisfyingpred(c) == true - range(min, max)
-
Create a PARSER(Char) which parse a char
csatisfyingmin <= c && c <= max.
- PARSER(List(Char)) many(char c)
-
Same as
many(char1(c)). - PARSER(List(String)) many(const char* s)
-
Same as
many(string1(s)). - PARSER(List(T)) many(PARSER(T) p)
-
Create a parser of PARSER(List(T)) type, which
- apply
pzero or more to a text. - returns a list of
List(T)type, which consists of the each result ofp. - NOTE :
parse(many(p), src, ex)- succeeds if
pexact matched N times (N ≥ 0) to the input fromsrcand N+1 thpfailed without consuming any input. - fails if
psucceeded without consuming any input. - otherwise fails after consumed some input.
- succeeds if
- NOTE :
Tmust be a member of TYPESET(0)
- apply
NOTE : many1(p) is same as cons(p, many(p)).
- PARSER(List(Char)) many1(char c)
-
Same as
many1(char1(c)). - PARSER(List(String)) many1(const char* s)
-
Same as
many1(string1(s)). - PARSER(List(T)) many1(PARSER(T) p)
-
Create a parser of PARSER(List(T)) type, which
- apply
ponce or more to a text. - returns a list of
List(T)type, which consists of the each result ofp. - NOTE :
parse(many1(p), src, ex)- succeeds if
pexact matched N times (N ≥ 1) to the input fromsrcand N+1 thpfailed without consuming any input. - fails if
psucceeded without consuming any input. - otherwise fails after consumed some input.
- succeeds if
- NOTE :
Tmust be a member of TYPESET(0)
- apply
- PARSER(List(T)) seq(PARSER(T) p, …)
-
Create a parser of PARSER(List(T)) type, which
- apply for all parsers
p, ...to a text. - return a list consists of the each retults of
p, .... - if a parser in the
p, ...failed, throws an error of it. - NOTE : For all parser in the
p, ..., whose type must be same, otherwise the behavior is undefined. - NOTE :
Tmust be a member of TYPESET(0)
- apply for all parsers
- PARSER(List(Char)) cons(char c, const char* cs)
-
Same as
cons(char1(c), string1(cs)). - PARSER(List(Char)) cons(char c, PARSER(List(Char)) ps)
-
Same as
cons(char1(c), ps). - PARSER(List(String)) cons(const char* s, PARSER(List(String)) ps)
-
Same as
cons(string1(s), ps). - PARSER(List(T)) cons(PARSER(T) p, PARSER(List(T)) ps)
-
Create a parser of PARSER(List(T)) type, which
- apply
pat first, and then applypsto the subsequent text. - return a list consists of the following:
- the result of
pand - elements of the result of
ps.
- the result of
- if
porpsfailed, throws an error of it. - NOTE :
Tmust be a member of TYPESET(0)
- apply
- PARSER(None) skip(char c)
-
Same as
skip(char1(c)). - PARSER(None) skip(const char* s)
-
Same as
skip(string1(s)). - PARSER(None) skip(PARSER(T) p)
-
Create a parser of PARSER(List(T)) type, which
- apply
pand returnsNONE. - a value returned by
pis discarded. - if
pfailed, throws error ofp. - NOTE :
Tmust be a member of TYPESET(1)
- apply
- PARSER(Char) skip1st(char c1, char c2)
-
Same as
skip1st(char1(c1), char1(c2)). - PARSER(Char) skip1st(const char* s, char c)
-
Same as
skip1st(string1(s), char1(c)). - PARSER(Char) skip1st(PARSER(S) p, char c)
-
Same as
skip1st(p, char1(c)). - PARSER(String) skip1st(char c, const char* s)
-
Same as
skip1st(char1(c), string1(s)). - PARSER(String) skip1st(const char* s1, const char* s2)
-
Same as
skip1st(string1(s1), string1(s2)). - PARSER(String) skip1st(PARSER(S) p, const char* s)
-
Same as
skip1st(p, string1(s)). - PARSER(T) skip1st(char c, PARSER(T) p)
-
Same as
skip1st(char1(c), p). - PARSER(T) skip1st(const char* s, PARSER(T) p)
-
Same as
skip1st(string1(s), p). - PARSER(T) skip1st(PARSER(S) p1, PARSER(T) p2)
-
Create a parser of PARSER(T) type, which
- apply
p1at first, and then applyp2to the subsequent text. - return the result of
p2if bothp1andp2success. - if
p1failed,p2is not applied and throws error ofp1. - if
p1success and thenp2failed, throws error ofp2. - NOTE :
SandTmust be a member of TYPESET(1) - NOTE :
SandTmay or may not be same.
(i.e.p1andp2may be a parser of same type or different type)
- apply
For example:
parseTest(skip1st(char1('a'), string1("bc")), "abc"); // -> "bc"
parseTest(skip1st(string1("ab"), char1('c')), "abc"); // -> 'c'- PARSER(Char) skip2nd(char c1, char c2)
-
Same as
skip2nd(char1(c1), char1(c2)). - PARSER(Char) skip2nd(char c, const char* s)
-
Same as
skip2nd(char1(c), string1(s)). - PARSER(Char) skip2nd(char c, PARSER(S) p)
-
Same as
skip2nd(char1(c), p). - PARSER(String) skip2nd(const char* s, char c)
-
Same as
skip2nd(string1(s), char1(c)). - PARSER(String) skip2nd(const char* s1, const char* s2)
-
Same as
skip2nd(string1(s1), string1(s2)). - PARSER(String) skip2nd(const char* s, PARSER(S) p)
-
Same as
skip2nd(string1(s), p). - PARSER(T) skip2nd(PARSER(T) p, char c)
-
Same as
skip2nd(p, char1(c)). - PARSER(T) skip2nd(PARSER(T) p, const char* s)
-
Same as
skip2nd(p, string1(s)). - PARSER(T) skip2nd(PARSER(T) p1, PARSER(S) p2)
-
Create a parser of PARSER(T) type, which
- apply
p1at first, and then applyp2to the subsequent text. - return the result of
p1if bothp1andp2success. - if
p1failed,p2is not applied and throws error ofp1. - if
p1success and thenp2failed, throws error ofp2. - NOTE :
SandTmust be a member of TYPESET(1) - NOTE :
SandTmay or may not be same.
(i.e.p1andp2may be a parser of same type or different type)
- apply
For example:
parseTest(skip2nd(char1('a'), string1("bc")), "abc"); // -> 'a'
parseTest(skip2nd(string1("ab"), char1('c')), "abc"); // -> "ab"NOTE : token(p) is same as skip2nd(p, spaces).
- PARSER(Char) token(char c)
-
Same as
token(char1(c)). - PARSER(String) token(const char* s)
-
Same as
token(string1(c)). - PARSER(T) token(PARSER(T) p)
-
Create a parser of PARSER(T) type, which
- apply
pat first, then - skip any trailing white-spaces, and
- return the result of
p. - NOTE :
Tmust be a member of TYPESET(1)
- apply
- PARSER(Char) either(char c1, char c2)
-
Same as
either(char1(c1), char1(c2)). - PARSER(Char) either(char c, PARSER(Char) p)
-
Same as
either(char1(c), p)). - PARSER(Char) either(PARSER(Char) p, char c)
-
Same as
either(p, char1(c))). - PARSER(String) either(const char* s1, const char* s2)
-
Same as
either(string1(s1), string1(s2)). - PARSER(String) either(const char* s, PARSER(String) p)
-
Same as
either(string1(s), p). - PARSER(String) either(PARSER(String) p, const char* s)
-
Same as
either(p, string1(s)). - PARSER(T) either(PARSER(T) p1, PARSER(T) p2)
-
Create a parser of PARSER(T) type, which
- return result of
p1ifp1succeeded, - if
p1consumed one or more chars and failed, throw error ofp1, - if
p1consumed no chars and failed, return result ofp2, or - throw error of
p2 - NOTE :
Tmust be a member of TYPESET(1)
- return result of
- PARSER(Char) tryp(char c)
-
Same as
tryp(char1(c)). - PARSER(String) tryp(const char* s)
-
Same as
tryp(string1(s)). - PARSER(T) tryp(PARSER(T) p)
-
Create a parser of PARSER(T) type, which
- return result of
pifpsuccess, - otherwise rewind the input-state back then throw error of
p. - NOTE :
Tmust be a member of TYPESET(1)
- return result of
NOTE : This section is mainly described for developers of CPARSEC2 library, not for users at the present.
- TYPEDEF_PARSER(T, R)
-
Define new concrete
PARSER(T)type andRETURN_TYPE(PARSER(T)).A parser of type
PARSER(T)returns a value of typeRwhen the parser was applied to a text.
(i.e.RETURN_TYPE(PARSER(T))will beR) - DECLARE_PARSER(T)
-
Declares functions/methods for
PARSER(T). - DEFINE_PARSER(T)
-
Defines functions/methods for
PARSER(T). - void SHOW(T)(R x) {
/* print x; */} -
Defines function
void SHOW(T)(R x).- NOTE :
void SHOW(T)(R x)is called byparseTest(p, text)to printx. - NOTE :
xis the result of parserpapplied to thetext.
- NOTE :
Example: ‘IntParser.h’
#include <cparsec2.h>
/* Defines PARSER(Int) type, and RETURN_TYPE(PARSER(T)) as int */
TYPEDEF_PARSER(Int, int);
/* Declares functions/methods for PARSER(Int) */
DECLARE_PARSER(Int);Example: ‘IntParser.c’
#include "IntParser.h"
/* Defines (implement) functions/methods for PARSER(Int) */
DEFINE_PARSER(Int);
/* and defines void SHOW(Int)(int x) */
void SHOW(Int)(int x) {
printf("%d", x);
}- PARSER(T) PARSER_GEN(T)(PARSER_FN(T) f, void* arg)
-
Create new instance of
PARSER(T).
fis used as a function body of the parser instance, andargis argument to be passed tofwhen the parser instance was applied to a text. - PARESR_FN(T)
-
Type of function body of a parser instance of
PARSER(T)type.
PARSER_FN(T)is the type of function pointerRETURN_TYPE(PARSER(T)) (*)(void* arg, Source src, Ctx* ex).
For example, PARSER_GEN(Int) and PARSER_FN(Int) are defiened as follows:
typedef int (* PARSER_FN(Int))(void* arg, Source src, Ctx* ex);
PARSER(Int) PARSER_GEN(Int)(PARSER_FN(Int) f, void* arg);The below is a example of parser-generator mult(int a), which
- creates a parser of
PARSER(Int)type.- When the parser applied to one or more digits,
- it returns a
intvalue multiplied bya.
- it returns a
- When the parser applied to one or more digits,
Example: ‘mult.h’
#include "IntParser.h"
/* a parser generator 'mult(a)' */
PARSER(Int) mult(int a);Example: ‘mult.c’
#include <stdlib.h>
#include "IntParser.h"
/* function body of a parser to be generated by mult(a) */
static int mult_func(void* arg, Source src, Ctx* ex) {
int a = (int)(intptr_t)arg;
return a * atoi(parse(many1(digit), src, ex));
}
/* a parser generator 'mult(a)' */
PARSER(Int) mult(int a) {
/* construct an instance of PARSER(Int) */
return PARSER_GEN(Int)(mult_func, (void*)(intptr_t)a);
}To apply a parser, use parse(p, src, ctx), parseTest(p, text) and
PARSE_TEST(p, text) macros. These macros are fully generic and easy to use.
In the below example, using parse(p, src, ex).
Example: ‘main.c’
#include <stdio.h>
#include "mult.h"
int main(int argc, char** argv) {
UNUSED(argc);
UNUSED(argv);
/* initialize CPARSEC2 library */
cparsec2_init();
Ctx ctx;
TRY(&ctx) {
/* input text is "100 200" */
Source src = Source_new("100 200");
/* parse the input text */
int x = parse(mult(1), src, &ctx); /* x = 1 * 100 */
parse(spaces, src, &ctx); /* skip white-spaces */
int y = parse(mult(2), src, &ctx); /* y = 2 * 200 */
/* print x + y */
printf("%d\n", x + y);
return 0;
}
else {
printf("error:%s\n", ctx.msg);
return 1;
}
}For example in case of many(p) :
/* Name of MANY(T) */
#define MANY(T) CAT(many_, T)
/* Generic macro function `many(p)` */
#define many(p) (GENERIC_P(PARSER_CAST(p), MANY, TYPESET(0))(PARSER_CAST(p)))
// For example:
// - `many("abc")` is expanded to `MANY(String)(string1("abc"))`
// - `many(number)` is expanded to `MANY(Int)(number)`
/* Generic function prototype `MANY(T)(p)` */
#define DECLARE_MANY(T) PARSER(List(T)) MANY(T)(PARSER(T) p)
/* Declares `PARSER(List(T)) MANY(T)(PARSER(T) p);` for each T in TYPESET(0) */
FOREACH(DECLARE_MANY, TYPESET(0));
// `FOREACH(DECLARE_MANY, TYPESET(0));` is expanded to as follows:
// ~~~c
// PARSER(List(Char)) MANY(Char)(PARSER(Char) p);
// PARSER(List(String)) MANY(String)(PARSER(String) p);
// PARSER(List(Int)) MANY(Int)(PARSER(Int) p);
// ~~~
/* Implementation of `MANY(T)(p)` */
#define DEFINE_MANY(T) \
PARSER(List(T)) MANY(T)(PARSER(T) p) { \
/* implementation of MANY(T)(p) */ \
} \
END_OF_STATEMENTS
/* Defines `PARSER(List(T)) MANY(T)(PARSER(T) p)` for each T in TYPESET(0) */
FOREACH(DEFINE_MANY, TYPESET(0));
// `FOREACH(DEFINE_MANY, TYPESET(0));` is expanded to as follows:
// ~~~c
// PARSER(List(Char)) MANY(Char)(PARSER(Char) p) {
// /* implementation of MANY(T)(p) */
// }
// _Static_assert(1, "");
// PARSER(List(String)) MANY(String)(PARSER(String) p) {
// /* implementation of MANY(T)(p) */
// }
// _Static_assert(1, "");
// PARSER(List(Int)) MANY(Int)(PARSER(Int) p) {
// /* implementation of MANY(T)(p) */
// }
// _Static_assert(1, "");
// ~~~PARSER_CAST(expr) cast expr to a parser.
- if
exprwas a parser of supportedPARSER(T)type, returnsexpritself. - if
exprwas acharorconst char, returnschar1(expr). - if
exprwas achar*orconst char*, returnsstring1(expr).
GENERIC_METHOD(expr, C, F, args...) is a macro function to define a “C11
_Generic selection” expression.
GENERIC_METHOD(expr, C, F, args...)is expanded to_Generic(expr, C(T) : F(T), ...)for eachTinargs....
GENERIC_P(expr, F, args...) is a macro function to define a “C11 _Generic
selection” expression.
GENERIC_P(expr, F, args...)is expanded to_Generic(expr, PARSER(T) : F(T), ...)for eachTinargs....- Same as
GENERIC_METHOD(expr, PARSER, F, args...).
FOREACH(F, args...) is a macro function for unrolling statements.
FOREACH(F, args...)is expanded toF(T);for eachTinargs....
#define F(T) T CAT(T, _value)
FOREACH(F, char, int, double);
// `FOREACH(F, x, y, z)` is expanded to `F(x); F(y); F(z)`
// Therefore the above is expanded to as follows:
// ~~~c
// char char_value;
// int int_value;
// double double_value;
// ~~~Set of type-names.
- TYPESET(0)
-
A set of type-names for parser-combinators.
TYPESET(0)is expanded toChar, String, Int, None, Node. - TYPESET(1)
-
Another set of type-names for parser-combinators.
TYPESET(1)is expanded toChar, String, Int, None, Node, List(String), List(Int), List(None), List(Node). - ELEMENT_TYPESET
-
A set of type-names for element-type of generic-containers.
ELEMENT_TYPESETis expanded toPtr, Char, String, Int, None, Node
These macros are convenient and easy to use with
GENERIC_METHOD(expr, C, F, ...),GENERIC_P(expr, F, ...), andFOREACH(F, ...).
For example :
GENERIC_P(expr, F, TYPESET(0))(expr);The above code is expanded as follows:
_Generic(expr, PARSER(Char) : F(Char), PARSER(String) : F(String), PARSER(Int) : F(Int))(expr);
- Where is
List(float)?- Where is
PARSER(double)?- How to add
List(UserType),Buff(UserType), andPARSER(UserType)?
Good question!
The CPARSEC2 library is ready to extend itself against user-defined types.
To extend the library,
- Define
CPARSEC2_USER_TYPESETmacro, before#include <cparsec2.h> - Call
CPARSEC2_DEFINE_USER_TYPESET()macro, after#include <cparsec2.h> - Define
void SHOW(U)(U x)function for each typeUinCPARSEC2_USER_TYPESET.
The following sections show an example how to add user-defined type Person to
the CPARSEC2 library. See also example/extend_cparsec2.
Here is an example that is extending CPARSEC2 library against user-defined type
Person.
my_cparsec2.h - a header file of extended CPARSEC2 library:
// (1) Define types
typedef struct {
const char* name;
int age;
} Person;
// (2) Define 'CPARSEC2_USER_TYPESET' macro,
// which should be a list of type names. (comma-separated)
#define CPARSEC2_USER_TYPESET Person
// (3) Then include 'cparsec2.h'
#include <cparsec2.h>my_cparsec2.c - an implementation of extended CPARSEC2 library:
// (1) include 'my_cparsec2.h'
#include "my_cparsec2.h"
// (2) Call CPARSEC2_DEFINE_USER_TYPESET() macro, which defines implementation
// of the following classes/APIs for each U in CPARSEC2_USER_TYPESET:
// - Buff(U),
// - List(U),
// - PARSER(U),
// - PARSER(List(U)),
// - All APIs for these classes such as `parse(p, src, ex)`, and
// - All parser-combinators such as `many(p)`, `either(p1, p2)`, etc.
CPARSEC2_DEFINE_USER_TYPESET();
// (3) Define function `void SHOW(U)(U x)` for each U in CPARSEC2_USER_TYPESET.
void SHOW(Person)(Person x) {
printf("<Person:.name=\"%s\", .age=%d>", x.name, x.age);
}That’s all.
Now you can use Buff(Person), List(Person), PARSER(Person),
PARSER(List(Person)), all APIs for these classes, and all parser-combinators
for PARSER(Person).
Here is the application sample:
main.c - an application using the extended CPARSEC2 library:
#include "my_cparsec2.h"
// implementation of 'person' parser
Person person_fn(void* arg, Source src, Ctx* ex) {
UNUSED(arg);
parse(token((char)'('), src, ex);
const char* name = parse(token(many1(letter)), src, ex);
parse(token((char)','), src, ex);
int age = parse(number, src, ex);
parse(token((char)')'), src, ex);
return (Person){.name = name, .age = age};
}
int main() {
cparsec2_init();
PARSER(Person) person = PARSER_GEN(Person)(person_fn, NULL);
PARSE_TEST(many(person), "(Alice, 19) (Bob, 24)");
// -> [<Person:.name="Alice", .age=19>, <Person:.name="Bob", .age=24>]
cparsec2_end();
}