diff --git a/bootstrap/doc/re2c.1 b/bootstrap/doc/re2c.1 index 1ccf3e133..1b54b7f74 100644 --- a/bootstrap/doc/re2c.1 +++ b/bootstrap/doc/re2c.1 @@ -32,7 +32,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] re2c \- generate fast lexical analyzers for C/C++ .SH SYNOPSIS .sp -Note: examples are in C++ (but can be easily adapted to C). +Note: some examples are in C++ (but can be adapted to C). .sp re2c \fB[ OPTIONS ]\fP \fB[ WARNINGS ]\fP \fBINPUT\fP .sp @@ -56,19 +56,19 @@ decimal number: // re2c $INPUT \-o $OUTPUT \-i \-\-case\-ranges #include -bool lex(const char *s) { +int lex(const char *s) { const char *YYCURSOR = s; /*!re2c re2c:yyfill:enable = 0; re2c:define:YYCTYPE = char; - [1\-9][0\-9]* { return true; } - * { return false; } + [1\-9][0\-9]* { return 0; } + * { return 1; } */ } int main() { - assert(lex(\(dq1234\(dq)); + assert(lex(\(dq1234\(dq) == 0); return 0; } @@ -87,7 +87,7 @@ In the output re2c replaced the block in the middle with the generated code: // re2c $INPUT \-o $OUTPUT \-i \-\-case\-ranges #include -bool lex(const char *s) { +int lex(const char *s) { const char *YYCURSOR = s; { @@ -99,7 +99,7 @@ bool lex(const char *s) { } yy1: ++YYCURSOR; - { return false; } + { return 1; } yy2: yych = *++YYCURSOR; switch (yych) { @@ -107,13 +107,13 @@ yy2: default: goto yy3; } yy3: - { return true; } + { return 0; } } } int main() { - assert(lex(\(dq1234\(dq)); + assert(lex(\(dq1234\(dq) == 0); return 0; } @@ -2701,45 +2701,45 @@ Here is an example of a program that reads input file \fBinput.txt\fP in chunks #define BUFSIZE 4095 -struct Input { +typedef struct { FILE *file; char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; // +1 for sentinel - bool eof; -}; + int eof; +} Input; -static int fill(Input &in) { - if (in.eof) return 1; +static int fill(Input *in) { + if (in\->eof) return 1; - const size_t shift = in.tok \- in.buf; - const size_t used = in.lim \- in.tok; + const size_t shift = in\->tok \- in\->buf; + const size_t used = in\->lim \- in\->tok; // Error: lexeme too long. In real life could reallocate a larger buffer. if (shift < 1) return 2; // Shift buffer contents (discard everything up to the current token). - memmove(in.buf, in.tok, used); - in.lim \-= shift; - in.cur \-= shift; - in.mar \-= shift; - in.tok \-= shift; + memmove(in\->buf, in\->tok, used); + in\->lim \-= shift; + in\->cur \-= shift; + in\->mar \-= shift; + in\->tok \-= shift; // Fill free space at the end of buffer with new data from file. - in.lim += fread(in.lim, 1, BUFSIZE \- used, in.file); - in.lim[0] = 0; - in.eof = in.lim < in.buf + BUFSIZE; + in\->lim += fread(in\->lim, 1, BUFSIZE \- used, in\->file); + in\->lim[0] = 0; + in\->eof = in\->lim < in\->buf + BUFSIZE; return 0; } -static int lex(Input &in) { +static int lex(Input *in) { int count = 0; loop: - in.tok = in.cur; + in\->tok = in\->cur; /*!re2c re2c:api:style = free\-form; re2c:define:YYCTYPE = char; - re2c:define:YYCURSOR = in.cur; - re2c:define:YYMARKER = in.mar; - re2c:define:YYLIMIT = in.lim; + re2c:define:YYCURSOR = in\->cur; + re2c:define:YYMARKER = in\->mar; + re2c:define:YYLIMIT = in\->lim; re2c:define:YYFILL = \(dqfill(in) == 0\(dq; re2c:eof = 0; @@ -2774,7 +2774,7 @@ int main() { in.lim[0] = 0; // Run the lexer. - assert(lex(in) == count); + assert(lex(&in) == count); // Cleanup: remove input file. fclose(in.file); @@ -2842,57 +2842,57 @@ Here is an example of a program that reads input file \fBinput.txt\fP in chunks /*!max:re2c*/ #define BUFSIZE (4096 \- YYMAXFILL) -struct Input { +typedef struct { FILE *file; char buf[BUFSIZE + YYMAXFILL], *lim, *cur, *tok; - bool eof; -}; + int eof; +} Input; -static int fill(Input &in, size_t need) { - if (in.eof) return 1; +static int fill(Input *in, size_t need) { + if (in\->eof) return 1; - const size_t shift = in.tok \- in.buf; - const size_t used = in.lim \- in.tok; + const size_t shift = in\->tok \- in\->buf; + const size_t used = in\->lim \- in\->tok; // Error: lexeme too long. In real life could reallocate a larger buffer. if (shift < need) return 2; // Shift buffer contents (discard everything up to the current token). - memmove(in.buf, in.tok, used); - in.lim \-= shift; - in.cur \-= shift; - in.tok \-= shift; + memmove(in\->buf, in\->tok, used); + in\->lim \-= shift; + in\->cur \-= shift; + in\->tok \-= shift; // Fill free space at the end of buffer with new data from file. - in.lim += fread(in.lim, 1, BUFSIZE \- used, in.file); + in\->lim += fread(in\->lim, 1, BUFSIZE \- used, in\->file); // If read less than expected, this is end of input => add zero padding // so that the lexer can access characters at the end of buffer. - if (in.lim < in.buf + BUFSIZE) { - in.eof = true; - memset(in.lim, 0, YYMAXFILL); - in.lim += YYMAXFILL; + if (in\->lim < in\->buf + BUFSIZE) { + in\->eof = 1; + memset(in\->lim, 0, YYMAXFILL); + in\->lim += YYMAXFILL; } return 0; } -static int lex(Input &in) { +static int lex(Input *in) { int count = 0; loop: - in.tok = in.cur; + in\->tok = in\->cur; /*!re2c re2c:api:style = free\-form; re2c:define:YYCTYPE = char; - re2c:define:YYCURSOR = in.cur; - re2c:define:YYLIMIT = in.lim; + re2c:define:YYCURSOR = in\->cur; + re2c:define:YYLIMIT = in\->lim; re2c:define:YYFILL = \(dqif (fill(in, @@) != 0) return \-1;\(dq; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; [\ex00] { // Check that it is the sentinel, not some unexpected null. - return in.tok == in.lim \- YYMAXFILL ? count : \-1; + return in\->tok == in\->lim \- YYMAXFILL ? count : \-1; } str { ++count; goto loop; } [ ]+ { goto loop; } @@ -2914,14 +2914,14 @@ int main() { int count = 3 * BUFSIZE; // number of quoted strings written to file // Initialize lexer state: all pointers are at the end of buffer. - // This immediately triggers YYFILL, as the check \(gain.cur < in.lim\(ga fails. + // This immediately triggers YYFILL, as the check \(gain\->cur < in\->lim\(ga fails. Input in; in.file = fopen(fname, \(dqr\(dq); in.cur = in.tok = in.lim = in.buf + BUFSIZE; in.eof = 0; // Run the lexer. - assert(lex(in) == count); + assert(lex(&in) == count); // Cleanup: remove input file. fclose(in.file); @@ -2966,10 +2966,7 @@ blocks. static const uint64_t ERROR = UINT64_MAX; -template static void add(uint64_t &u, char d) { - u = u * BASE + d; - if (u > UINT32_MAX) u = ERROR; -} +#define CHECK(n) if (n > UINT32_MAX) return ERROR; static uint64_t parse_u32(const char *s) { const char *YYCURSOR = s, *YYMARKER; @@ -2990,27 +2987,27 @@ static uint64_t parse_u32(const char *s) { bin: /*!re2c end { return u; } - [01] { add<2>(u, YYCURSOR[\-1] \- \(aq0\(aq); goto bin; } + [01] { u = u * 2 + (YYCURSOR[\-1] \- \(aq0\(aq); CHECK(u); goto bin; } * { return ERROR; } */ oct: /*!re2c end { return u; } - [0\-7] { add<8>(u, YYCURSOR[\-1] \- \(aq0\(aq); goto oct; } + [0\-7] { u = u * 8 + (YYCURSOR[\-1] \- \(aq0\(aq); CHECK(u); goto oct; } * { return ERROR; } */ dec: /*!re2c end { return u; } - [0\-9] { add<10>(u, YYCURSOR[\-1] \- \(aq0\(aq); goto dec; } + [0\-9] { u = u * 10 + (YYCURSOR[\-1] \- \(aq0\(aq); CHECK(u); goto dec; } * { return ERROR; } */ hex: /*!re2c end { return u; } - [0\-9] { add<16>(u, YYCURSOR[\-1] \- \(aq0\(aq); goto hex; } - [a\-f] { add<16>(u, YYCURSOR[\-1] \- \(aqa\(aq + 10); goto hex; } - [A\-F] { add<16>(u, YYCURSOR[\-1] \- \(aqA\(aq + 10); goto hex; } + [0\-9] { u = u * 16 + (YYCURSOR[\-1] \- \(aq0\(aq); CHECK(u); goto hex; } + [a\-f] { u = u * 16 + (YYCURSOR[\-1] \- \(aqa\(aq + 10); CHECK(u); goto hex; } + [A\-F] { u = u * 16 + (YYCURSOR[\-1] \- \(aqA\(aq + 10); CHECK(u); goto hex; } * { return ERROR; } */ } @@ -3126,11 +3123,6 @@ number of the initial condition generated with \fBconditions\fP block. static const uint64_t ERROR = UINT64_MAX; /*!conditions:re2c*/ -template static void add(uint64_t &u, char d) { - u = u * BASE + d; - if (u > UINT32_MAX) u = ERROR; -} - static uint64_t parse_u32(const char *s) { const char *YYCURSOR = s, *YYMARKER; int c = yycinit; @@ -3152,12 +3144,13 @@ static uint64_t parse_u32(const char *s) { \(dq\ex00\(dq { return u; } - [01] { add<2>(u, YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_bin; } - [0\-7] { add<8>(u, YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_oct; } - [0\-9] { add<10>(u, YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_dec; } - [0\-9] { add<16>(u, YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_hex; } - [a\-f] { add<16>(u, YYCURSOR[\-1] \- \(aqa\(aq + 10); goto yyc_hex; } - [A\-F] { add<16>(u, YYCURSOR[\-1] \- \(aqA\(aq + 10); goto yyc_hex; } + [01] { u = u * 2 + (YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_bin; } + [0\-7] { u = u * 8 + (YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_oct; } + [0\-9] { u = u * 10 + (YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_dec; } + [0\-9] { u = u * 16 + (YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_hex; } + [a\-f] { u = u * 16 + (YYCURSOR[\-1] \- \(aqa\(aq + 10); goto yyc_hex; } + [A\-F] { u = u * 16 + (YYCURSOR[\-1] \- \(aqA\(aq + 10); goto yyc_hex; } + { if (u > UINT32_MAX) return ERROR; } */ } @@ -3238,51 +3231,51 @@ sent, or when there is an error. // In real world use a larger buffer. #define BUFSIZE 10 -struct State { +typedef struct { FILE *file; char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; int state; -}; +} State; typedef enum {END, READY, WAITING, BAD_PACKET, BIG_PACKET} Status; -static Status fill(State &st) { - const size_t shift = st.tok \- st.buf; - const size_t used = st.lim \- st.tok; +static Status fill(State *st) { + const size_t shift = st\->tok \- st\->buf; + const size_t used = st\->lim \- st\->tok; const size_t free = BUFSIZE \- used; // Error: no space. In real life can reallocate a larger buffer. if (free < 1) return BIG_PACKET; // Shift buffer contents (discard already processed data). - memmove(st.buf, st.tok, used); - st.lim \-= shift; - st.cur \-= shift; - st.mar \-= shift; - st.tok \-= shift; + memmove(st\->buf, st\->tok, used); + st\->lim \-= shift; + st\->cur \-= shift; + st\->mar \-= shift; + st\->tok \-= shift; // Fill free space at the end of buffer with new data. - const size_t read = fread(st.lim, 1, free, st.file); - st.lim += read; - st.lim[0] = 0; // append sentinel symbol + const size_t read = fread(st\->lim, 1, free, st\->file); + st\->lim += read; + st\->lim[0] = 0; // append sentinel symbol return READY; } -static Status lex(State &st, unsigned int *recv) { +static Status lex(State *st, unsigned int *recv) { char yych; /*!getstate:re2c*/ for (;;) { - st.tok = st.cur; + st\->tok = st\->cur; /*!re2c re2c:api:style = free\-form; re2c:define:YYCTYPE = \(dqchar\(dq; - re2c:define:YYCURSOR = \(dqst.cur\(dq; - re2c:define:YYMARKER = \(dqst.mar\(dq; - re2c:define:YYLIMIT = \(dqst.lim\(dq; - re2c:define:YYGETSTATE = \(dqst.state\(dq; - re2c:define:YYSETSTATE = \(dqst.state = @@;\(dq; + re2c:define:YYCURSOR = \(dqst\->cur\(dq; + re2c:define:YYMARKER = \(dqst\->mar\(dq; + re2c:define:YYLIMIT = \(dqst\->lim\(dq; + re2c:define:YYGETSTATE = \(dqst\->state\(dq; + re2c:define:YYSETSTATE = \(dqst\->state = @@;\(dq; re2c:define:YYFILL = \(dqreturn WAITING;\(dq; re2c:eof = 0; @@ -3318,7 +3311,7 @@ void test(const char **packets, Status expect) { Status status; unsigned int send = 0, recv = 0; for (;;) { - status = lex(st, &recv); + status = lex(&st, &recv); if (status == END) { LOG(\(dqdone: got %u packets\en\(dq, recv); break; @@ -3329,7 +3322,7 @@ void test(const char **packets, Status expect) { fprintf(fw, \(dq%s\(dq, *packets++); ++send; } - status = fill(st); + status = fill(&st); LOG(\(dqqueue: \(aq%s\(aq\en\(dq, st.buf); if (status == BIG_PACKET) { LOG(\(dqerror: packet too big\en\(dq); @@ -3416,7 +3409,7 @@ blocks. // earlier. Default rule * occurs in all three blocks; the local (not // inherited) definition takes priority. -enum What { COLOR, FISH, DUNNO }; +typedef enum { COLOR, FISH, DUNNO } What; /*!rules:re2c:colors * { assert(false); } @@ -3607,7 +3600,7 @@ See below for a more complex example that uses \fBYYFILL\fP\&. #include #include -struct SemVer { int major, minor, patch; }; +typedef struct { int major, minor, patch; } SemVer; static int s2n(const char *s, const char *e) { // pre\-parsed string to number int n = 0; @@ -3615,7 +3608,7 @@ static int s2n(const char *s, const char *e) { // pre\-parsed string to number return n; } -static bool lex(const char *str, SemVer &ver) { +static int lex(const char *str, SemVer *ver) { const char *YYCURSOR = str, *YYMARKER; // User\-defined tag variables that are available in semantic action. @@ -3632,20 +3625,20 @@ static bool lex(const char *str, SemVer &ver) { num = [0\-9]+; @t1 num @t2 \(dq.\(dq @t3 num @t4 (\(dq.\(dq @t5 num)? [\ex00] { - ver.major = s2n(t1, t2); - ver.minor = s2n(t3, t4); - ver.patch = t5 != NULL ? s2n(t5, YYCURSOR \- 1) : 0; - return true; + ver\->major = s2n(t1, t2); + ver\->minor = s2n(t3, t4); + ver\->patch = t5 != NULL ? s2n(t5, YYCURSOR \- 1) : 0; + return 0; } - * { return false; } + * { return 1; } */ } int main() { SemVer v; - assert(lex(\(dq23.34\(dq, v) && v.major == 23 && v.minor == 34 && v.patch == 0); - assert(lex(\(dq1.2.999\(dq, v) && v.major == 1 && v.minor == 2 && v.patch == 999); - assert(!lex(\(dq1.a\(dq, v)); + assert(lex(\(dq23.34\(dq, &v) == 0 && v.major == 23 && v.minor == 34 && v.patch == 0); + assert(lex(\(dq1.2.999\(dq, &v) == 0 && v.major == 1 && v.minor == 2 && v.patch == 999); + assert(lex(\(dq1.a\(dq, &v) == 1); return 0; } @@ -3801,7 +3794,7 @@ Here is an example of using capturing groups to parse semantic versions. #include #include -struct SemVer { int major, minor, patch; }; +typedef struct { int major, minor, patch; } SemVer; static int s2n(const char *s, const char *e) { // pre\-parsed string to number int n = 0; @@ -3809,7 +3802,7 @@ static int s2n(const char *s, const char *e) { // pre\-parsed string to number return n; } -static bool lex(const char *str, SemVer &ver) { +static int lex(const char *str, SemVer *ver) { const char *YYCURSOR = str, *YYMARKER; // Final tag variables available in semantic action. @@ -3827,20 +3820,20 @@ static bool lex(const char *str, SemVer &ver) { (num) \(dq.\(dq (num) (\(dq.\(dq num)? [\ex00] { (void) yytl0; (void) yytr0; // some variables are unused - ver.major = s2n(yytl1, yytr1); - ver.minor = s2n(yytl2, yytr2); - ver.patch = yytl3 ? s2n(yytl3 + 1, yytr3) : 0; - return true; + ver\->major = s2n(yytl1, yytr1); + ver\->minor = s2n(yytl2, yytr2); + ver\->patch = yytl3 ? s2n(yytl3 + 1, yytr3) : 0; + return 0; } - * { return false; } + * { return 1; } */ } int main() { SemVer v; - assert(lex(\(dq23.34\(dq, v) && v.major == 23 && v.minor == 34 && v.patch == 0); - assert(lex(\(dq1.2.999\(dq, v) && v.major == 1 && v.minor == 2 && v.patch == 999); - assert(!lex(\(dq1.a\(dq, v)); + assert(lex(\(dq23.34\(dq, &v) == 0 && v.major == 23 && v.minor == 34 && v.patch == 0); + assert(lex(\(dq1.2.999\(dq, &v) == 0 && v.major == 1 && v.minor == 2 && v.patch == 999); + assert(lex(\(dq1.a\(dq, &v) == 1); return 0; } @@ -4155,30 +4148,30 @@ grammar and is unknown to the programmer). #include \(dqlexer/state.h\(dq // the header is generated by re2c /*!header:re2c:on*/ -struct LexerState { +typedef struct { const char *str, *cur; /*!stags:re2c format = \(dqconst char *@@;\(dq; */ -}; +} LexerState; /*!header:re2c:off*/ -long lex(LexerState& st) { +long lex(LexerState* st) { const char *t; /*!re2c re2c:header = \(dqlexer/state.h\(dq; re2c:yyfill:enable = 0; re2c:define:YYCTYPE = char; - re2c:define:YYCURSOR = \(dqst.cur\(dq; + re2c:define:YYCURSOR = \(dqst\->cur\(dq; re2c:tags = 1; - re2c:tags:expression = \(dqst.@@\(dq; + re2c:tags:expression = \(dqst\->@@\(dq; - [a]* @t [b]* { return t \- st.str; } + [a]* @t [b]* { return t \- st\->str; } */ } int main() { const char *s = \(dqab\(dq; LexerState st = { s, s /*!stags:re2c format = \(dq, NULL\(dq; */ }; - assert(lex(st) == 1); + assert(lex(&st) == 1); return 0; } @@ -4194,13 +4187,11 @@ int main() { .ft C /* Generated by re2c */ - typedef struct { const char *str, *cur; const char *yyt1; } LexerState; - .ft P .fi .UNINDENT diff --git a/build/split_man.py b/build/split_man.py index 618b27f56..e83223bdf 100644 --- a/build/split_man.py +++ b/build/split_man.py @@ -26,7 +26,7 @@ src_ext = b'c' hdr_ext = b'h' lang_name = b'C/C++' - disclaimer = b'Note: examples are in C++ (but can be easily adapted to C).' + disclaimer = b'Note: some examples are in C++ (but can be adapted to C).' elif lang == b'd': src_ext = b'd' lang_name = b'D' diff --git a/examples/c/01_basic.c b/examples/c/01_basic.c index 56df5c677..d9defe2a2 100644 --- a/examples/c/01_basic.c +++ b/examples/c/01_basic.c @@ -2,7 +2,7 @@ // re2c $INPUT -o $OUTPUT -i --case-ranges #include -bool lex(const char *s) { +int lex(const char *s) { const char *YYCURSOR = s; { @@ -14,7 +14,7 @@ bool lex(const char *s) { } yy1: ++YYCURSOR; - { return false; } + { return 1; } yy2: yych = *++YYCURSOR; switch (yych) { @@ -22,12 +22,12 @@ bool lex(const char *s) { default: goto yy3; } yy3: - { return true; } + { return 0; } } } int main() { - assert(lex("1234")); + assert(lex("1234") == 0); return 0; } diff --git a/examples/c/01_basic.re b/examples/c/01_basic.re index 9dbdea0d8..d0be2db1d 100644 --- a/examples/c/01_basic.re +++ b/examples/c/01_basic.re @@ -1,18 +1,18 @@ // re2c $INPUT -o $OUTPUT -i --case-ranges #include -bool lex(const char *s) { +int lex(const char *s) { const char *YYCURSOR = s; /*!re2c re2c:yyfill:enable = 0; re2c:define:YYCTYPE = char; - [1-9][0-9]* { return true; } - * { return false; } + [1-9][0-9]* { return 0; } + * { return 1; } */ } int main() { - assert(lex("1234")); + assert(lex("1234") == 0); return 0; } diff --git a/examples/c/conditions/parse_u32_blocks.c b/examples/c/conditions/parse_u32_blocks.c index 23b37b005..a516fb805 100644 --- a/examples/c/conditions/parse_u32_blocks.c +++ b/examples/c/conditions/parse_u32_blocks.c @@ -6,10 +6,7 @@ static const uint64_t ERROR = UINT64_MAX; -static void add(uint32_t base, uint64_t &number, char digit) { - number = number * base + digit; - if (number > UINT32_MAX) number = ERROR; -} +#define CHECK(n) if (n > UINT32_MAX) return ERROR; static uint64_t parse_u32(const char *s) { const char *YYCURSOR = s, *YYMARKER; @@ -116,7 +113,7 @@ static uint64_t parse_u32(const char *s) { { return ERROR; } yy13: ++YYCURSOR; - { add(2, u, YYCURSOR[-1] - '0'); goto bin; } + { u = u * 2 + (YYCURSOR[-1] - '0'); CHECK(u); goto bin; } } oct: @@ -144,7 +141,7 @@ static uint64_t parse_u32(const char *s) { { return ERROR; } yy17: ++YYCURSOR; - { add(8, u, YYCURSOR[-1] - '0'); goto oct; } + { u = u * 8 + (YYCURSOR[-1] - '0'); CHECK(u); goto oct; } } dec: @@ -174,7 +171,7 @@ static uint64_t parse_u32(const char *s) { { return ERROR; } yy21: ++YYCURSOR; - { add(10, u, YYCURSOR[-1] - '0'); goto dec; } + { u = u * 10 + (YYCURSOR[-1] - '0'); CHECK(u); goto dec; } } hex: @@ -216,13 +213,13 @@ static uint64_t parse_u32(const char *s) { { return ERROR; } yy25: ++YYCURSOR; - { add(16, u, YYCURSOR[-1] - '0'); goto hex; } + { u = u * 16 + (YYCURSOR[-1] - '0'); CHECK(u); goto hex; } yy26: ++YYCURSOR; - { add(16, u, YYCURSOR[-1] - 'A' + 10); goto hex; } + { u = u * 16 + (YYCURSOR[-1] - 'A' + 10); CHECK(u); goto hex; } yy27: ++YYCURSOR; - { add(16, u, YYCURSOR[-1] - 'a' + 10); goto hex; } + { u = u * 16 + (YYCURSOR[-1] - 'a' + 10); CHECK(u); goto hex; } } } diff --git a/examples/c/conditions/parse_u32_blocks.re b/examples/c/conditions/parse_u32_blocks.re index 8e25c8003..6a4f5808b 100644 --- a/examples/c/conditions/parse_u32_blocks.re +++ b/examples/c/conditions/parse_u32_blocks.re @@ -5,10 +5,7 @@ static const uint64_t ERROR = UINT64_MAX; -static void add(uint32_t base, uint64_t &number, char digit) { - number = number * base + digit; - if (number > UINT32_MAX) number = ERROR; -} +#define CHECK(n) if (n > UINT32_MAX) return ERROR; static uint64_t parse_u32(const char *s) { const char *YYCURSOR = s, *YYMARKER; @@ -29,27 +26,27 @@ static uint64_t parse_u32(const char *s) { bin: /*!re2c end { return u; } - [01] { add(2, u, YYCURSOR[-1] - '0'); goto bin; } + [01] { u = u * 2 + (YYCURSOR[-1] - '0'); CHECK(u); goto bin; } * { return ERROR; } */ oct: /*!re2c end { return u; } - [0-7] { add(8, u, YYCURSOR[-1] - '0'); goto oct; } + [0-7] { u = u * 8 + (YYCURSOR[-1] - '0'); CHECK(u); goto oct; } * { return ERROR; } */ dec: /*!re2c end { return u; } - [0-9] { add(10, u, YYCURSOR[-1] - '0'); goto dec; } + [0-9] { u = u * 10 + (YYCURSOR[-1] - '0'); CHECK(u); goto dec; } * { return ERROR; } */ hex: /*!re2c end { return u; } - [0-9] { add(16, u, YYCURSOR[-1] - '0'); goto hex; } - [a-f] { add(16, u, YYCURSOR[-1] - 'a' + 10); goto hex; } - [A-F] { add(16, u, YYCURSOR[-1] - 'A' + 10); goto hex; } + [0-9] { u = u * 16 + (YYCURSOR[-1] - '0'); CHECK(u); goto hex; } + [a-f] { u = u * 16 + (YYCURSOR[-1] - 'a' + 10); CHECK(u); goto hex; } + [A-F] { u = u * 16 + (YYCURSOR[-1] - 'A' + 10); CHECK(u); goto hex; } * { return ERROR; } */ } diff --git a/examples/c/conditions/parse_u32_conditions.c b/examples/c/conditions/parse_u32_conditions.c index 5c32389b4..7d2e41496 100644 --- a/examples/c/conditions/parse_u32_conditions.c +++ b/examples/c/conditions/parse_u32_conditions.c @@ -14,11 +14,6 @@ enum YYCONDTYPE { }; -static void add(uint32_t base, uint64_t &number, char digit) { - number = number * base + digit; - if (number > UINT32_MAX) number = ERROR; -} - static uint64_t parse_u32(const char *s) { const char *YYCURSOR = s, *YYMARKER; int c = yycinit; @@ -52,6 +47,7 @@ static uint64_t parse_u32(const char *s) { } yy1: ++YYCURSOR; + { if (u > UINT32_MAX) return ERROR; } { return ERROR; } yy2: yych = *(YYMARKER = ++YYCURSOR); @@ -128,13 +124,16 @@ static uint64_t parse_u32(const char *s) { } yy11: ++YYCURSOR; + { if (u > UINT32_MAX) return ERROR; } { return u; } yy12: ++YYCURSOR; + { if (u > UINT32_MAX) return ERROR; } { return ERROR; } yy13: ++YYCURSOR; - { add(2, u, YYCURSOR[-1] - '0'); goto yyc_bin; } + { if (u > UINT32_MAX) return ERROR; } + { u = u * 2 + (YYCURSOR[-1] - '0'); goto yyc_bin; } /* *********************************** */ yyc_dec: yych = *YYCURSOR; @@ -154,13 +153,16 @@ static uint64_t parse_u32(const char *s) { } yy15: ++YYCURSOR; + { if (u > UINT32_MAX) return ERROR; } { return u; } yy16: ++YYCURSOR; + { if (u > UINT32_MAX) return ERROR; } { return ERROR; } yy17: ++YYCURSOR; - { add(10, u, YYCURSOR[-1] - '0'); goto yyc_dec; } + { if (u > UINT32_MAX) return ERROR; } + { u = u * 10 + (YYCURSOR[-1] - '0'); goto yyc_dec; } /* *********************************** */ yyc_hex: yych = *YYCURSOR; @@ -192,19 +194,24 @@ static uint64_t parse_u32(const char *s) { } yy19: ++YYCURSOR; + { if (u > UINT32_MAX) return ERROR; } { return u; } yy20: ++YYCURSOR; + { if (u > UINT32_MAX) return ERROR; } { return ERROR; } yy21: ++YYCURSOR; - { add(16, u, YYCURSOR[-1] - '0'); goto yyc_hex; } + { if (u > UINT32_MAX) return ERROR; } + { u = u * 16 + (YYCURSOR[-1] - '0'); goto yyc_hex; } yy22: ++YYCURSOR; - { add(16, u, YYCURSOR[-1] - 'A' + 10); goto yyc_hex; } + { if (u > UINT32_MAX) return ERROR; } + { u = u * 16 + (YYCURSOR[-1] - 'A' + 10); goto yyc_hex; } yy23: ++YYCURSOR; - { add(16, u, YYCURSOR[-1] - 'a' + 10); goto yyc_hex; } + { if (u > UINT32_MAX) return ERROR; } + { u = u * 16 + (YYCURSOR[-1] - 'a' + 10); goto yyc_hex; } /* *********************************** */ yyc_oct: yych = *YYCURSOR; @@ -222,13 +229,16 @@ static uint64_t parse_u32(const char *s) { } yy25: ++YYCURSOR; + { if (u > UINT32_MAX) return ERROR; } { return u; } yy26: ++YYCURSOR; + { if (u > UINT32_MAX) return ERROR; } { return ERROR; } yy27: ++YYCURSOR; - { add(8, u, YYCURSOR[-1] - '0'); goto yyc_oct; } + { if (u > UINT32_MAX) return ERROR; } + { u = u * 8 + (YYCURSOR[-1] - '0'); goto yyc_oct; } } } diff --git a/examples/c/conditions/parse_u32_conditions.re b/examples/c/conditions/parse_u32_conditions.re index 9eb7a63b1..55230e14c 100644 --- a/examples/c/conditions/parse_u32_conditions.re +++ b/examples/c/conditions/parse_u32_conditions.re @@ -6,11 +6,6 @@ static const uint64_t ERROR = UINT64_MAX; /*!conditions:re2c*/ -static void add(uint32_t base, uint64_t &number, char digit) { - number = number * base + digit; - if (number > UINT32_MAX) number = ERROR; -} - static uint64_t parse_u32(const char *s) { const char *YYCURSOR = s, *YYMARKER; int c = yycinit; @@ -32,12 +27,13 @@ static uint64_t parse_u32(const char *s) { "\x00" { return u; } - [01] { add(2, u, YYCURSOR[-1] - '0'); goto yyc_bin; } - [0-7] { add(8, u, YYCURSOR[-1] - '0'); goto yyc_oct; } - [0-9] { add(10, u, YYCURSOR[-1] - '0'); goto yyc_dec; } - [0-9] { add(16, u, YYCURSOR[-1] - '0'); goto yyc_hex; } - [a-f] { add(16, u, YYCURSOR[-1] - 'a' + 10); goto yyc_hex; } - [A-F] { add(16, u, YYCURSOR[-1] - 'A' + 10); goto yyc_hex; } + [01] { u = u * 2 + (YYCURSOR[-1] - '0'); goto yyc_bin; } + [0-7] { u = u * 8 + (YYCURSOR[-1] - '0'); goto yyc_oct; } + [0-9] { u = u * 10 + (YYCURSOR[-1] - '0'); goto yyc_dec; } + [0-9] { u = u * 16 + (YYCURSOR[-1] - '0'); goto yyc_hex; } + [a-f] { u = u * 16 + (YYCURSOR[-1] - 'a' + 10); goto yyc_hex; } + [A-F] { u = u * 16 + (YYCURSOR[-1] - 'A' + 10); goto yyc_hex; } + { if (u > UINT32_MAX) return ERROR; } */ } diff --git a/examples/c/fill/01_fill.c b/examples/c/fill/01_fill.c index 0d9906f84..f762438a7 100644 --- a/examples/c/fill/01_fill.c +++ b/examples/c/fill/01_fill.c @@ -7,69 +7,69 @@ #define BUFSIZE 4095 -struct Input { +typedef struct { FILE *file; char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; // +1 for sentinel - bool eof; -}; + int eof; +} Input; -static int fill(Input &in) { - if (in.eof) return 1; +static int fill(Input *in) { + if (in->eof) return 1; - const size_t shift = in.tok - in.buf; - const size_t used = in.lim - in.tok; + const size_t shift = in->tok - in->buf; + const size_t used = in->lim - in->tok; // Error: lexeme too long. In real life could reallocate a larger buffer. if (shift < 1) return 2; // Shift buffer contents (discard everything up to the current token). - memmove(in.buf, in.tok, used); - in.lim -= shift; - in.cur -= shift; - in.mar -= shift; - in.tok -= shift; + memmove(in->buf, in->tok, used); + in->lim -= shift; + in->cur -= shift; + in->mar -= shift; + in->tok -= shift; // Fill free space at the end of buffer with new data from file. - in.lim += fread(in.lim, 1, BUFSIZE - used, in.file); - in.lim[0] = 0; - in.eof = in.lim < in.buf + BUFSIZE; + in->lim += fread(in->lim, 1, BUFSIZE - used, in->file); + in->lim[0] = 0; + in->eof = in->lim < in->buf + BUFSIZE; return 0; } -static int lex(Input &in) { +static int lex(Input *in) { int count = 0; loop: - in.tok = in.cur; + in->tok = in->cur; #line 45 "c/fill/01_fill.c" { char yych; yyFillLabel0: - yych = *in.cur; + yych = *in->cur; switch (yych) { case ' ': goto yy3; case '\'': goto yy5; default: - if (in.lim <= in.cur) { + if (in->lim <= in->cur) { if (fill(in) == 0) goto yyFillLabel0; goto yy10; } goto yy1; } yy1: - ++in.cur; + ++in->cur; yy2: #line 52 "c/fill/01_fill.re" { return -1; } #line 65 "c/fill/01_fill.c" yy3: - ++in.cur; + ++in->cur; yyFillLabel1: - yych = *in.cur; + yych = *in->cur; switch (yych) { case ' ': goto yy3; default: - if (in.lim <= in.cur) { + if (in->lim <= in->cur) { if (fill(in) == 0) goto yyFillLabel1; } goto yy4; @@ -79,40 +79,40 @@ static int lex(Input &in) { { goto loop; } #line 81 "c/fill/01_fill.c" yy5: - in.mar = ++in.cur; + in->mar = ++in->cur; yyFillLabel2: - yych = *in.cur; + yych = *in->cur; if (yych >= 0x01) goto yy7; - if (in.lim <= in.cur) { + if (in->lim <= in->cur) { if (fill(in) == 0) goto yyFillLabel2; goto yy2; } yy6: - ++in.cur; + ++in->cur; yyFillLabel3: - yych = *in.cur; + yych = *in->cur; yy7: switch (yych) { case '\'': goto yy8; case '\\': goto yy9; default: - if (in.lim <= in.cur) { + if (in->lim <= in->cur) { if (fill(in) == 0) goto yyFillLabel3; goto yy11; } goto yy6; } yy8: - ++in.cur; + ++in->cur; #line 54 "c/fill/01_fill.re" { ++count; goto loop; } #line 110 "c/fill/01_fill.c" yy9: - ++in.cur; + ++in->cur; yyFillLabel4: - yych = *in.cur; + yych = *in->cur; if (yych <= 0x00) { - if (in.lim <= in.cur) { + if (in->lim <= in->cur) { if (fill(in) == 0) goto yyFillLabel4; goto yy11; } @@ -124,7 +124,7 @@ static int lex(Input &in) { { return count; } #line 126 "c/fill/01_fill.c" yy11: - in.cur = in.mar; + in->cur = in->mar; goto yy2; } #line 56 "c/fill/01_fill.re" @@ -153,7 +153,7 @@ int main() { in.lim[0] = 0; // Run the lexer. - assert(lex(in) == count); + assert(lex(&in) == count); // Cleanup: remove input file. fclose(in.file); diff --git a/examples/c/fill/01_fill.re b/examples/c/fill/01_fill.re index 0b76db596..dbe184cba 100644 --- a/examples/c/fill/01_fill.re +++ b/examples/c/fill/01_fill.re @@ -5,45 +5,45 @@ #define BUFSIZE 4095 -struct Input { +typedef struct { FILE *file; char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; // +1 for sentinel - bool eof; -}; + int eof; +} Input; -static int fill(Input &in) { - if (in.eof) return 1; +static int fill(Input *in) { + if (in->eof) return 1; - const size_t shift = in.tok - in.buf; - const size_t used = in.lim - in.tok; + const size_t shift = in->tok - in->buf; + const size_t used = in->lim - in->tok; // Error: lexeme too long. In real life could reallocate a larger buffer. if (shift < 1) return 2; // Shift buffer contents (discard everything up to the current token). - memmove(in.buf, in.tok, used); - in.lim -= shift; - in.cur -= shift; - in.mar -= shift; - in.tok -= shift; + memmove(in->buf, in->tok, used); + in->lim -= shift; + in->cur -= shift; + in->mar -= shift; + in->tok -= shift; // Fill free space at the end of buffer with new data from file. - in.lim += fread(in.lim, 1, BUFSIZE - used, in.file); - in.lim[0] = 0; - in.eof = in.lim < in.buf + BUFSIZE; + in->lim += fread(in->lim, 1, BUFSIZE - used, in->file); + in->lim[0] = 0; + in->eof = in->lim < in->buf + BUFSIZE; return 0; } -static int lex(Input &in) { +static int lex(Input *in) { int count = 0; loop: - in.tok = in.cur; + in->tok = in->cur; /*!re2c re2c:api:style = free-form; re2c:define:YYCTYPE = char; - re2c:define:YYCURSOR = in.cur; - re2c:define:YYMARKER = in.mar; - re2c:define:YYLIMIT = in.lim; + re2c:define:YYCURSOR = in->cur; + re2c:define:YYMARKER = in->mar; + re2c:define:YYLIMIT = in->lim; re2c:define:YYFILL = "fill(in) == 0"; re2c:eof = 0; @@ -78,7 +78,7 @@ int main() { in.lim[0] = 0; // Run the lexer. - assert(lex(in) == count); + assert(lex(&in) == count); // Cleanup: remove input file. fclose(in.file); diff --git a/examples/c/fill/02_fill.c b/examples/c/fill/02_fill.c index 9b8f2820b..ff785a526 100644 --- a/examples/c/fill/02_fill.c +++ b/examples/c/fill/02_fill.c @@ -11,51 +11,51 @@ #define BUFSIZE (4096 - YYMAXFILL) -struct Input { +typedef struct { FILE *file; char buf[BUFSIZE + YYMAXFILL], *lim, *cur, *tok; - bool eof; -}; + int eof; +} Input; -static int fill(Input &in, size_t need) { - if (in.eof) return 1; +static int fill(Input *in, size_t need) { + if (in->eof) return 1; - const size_t shift = in.tok - in.buf; - const size_t used = in.lim - in.tok; + const size_t shift = in->tok - in->buf; + const size_t used = in->lim - in->tok; // Error: lexeme too long. In real life could reallocate a larger buffer. if (shift < need) return 2; // Shift buffer contents (discard everything up to the current token). - memmove(in.buf, in.tok, used); - in.lim -= shift; - in.cur -= shift; - in.tok -= shift; + memmove(in->buf, in->tok, used); + in->lim -= shift; + in->cur -= shift; + in->tok -= shift; // Fill free space at the end of buffer with new data from file. - in.lim += fread(in.lim, 1, BUFSIZE - used, in.file); + in->lim += fread(in->lim, 1, BUFSIZE - used, in->file); // If read less than expected, this is end of input => add zero padding // so that the lexer can access characters at the end of buffer. - if (in.lim < in.buf + BUFSIZE) { - in.eof = true; - memset(in.lim, 0, YYMAXFILL); - in.lim += YYMAXFILL; + if (in->lim < in->buf + BUFSIZE) { + in->eof = 1; + memset(in->lim, 0, YYMAXFILL); + in->lim += YYMAXFILL; } return 0; } -static int lex(Input &in) { +static int lex(Input *in) { int count = 0; loop: - in.tok = in.cur; + in->tok = in->cur; #line 55 "c/fill/02_fill.c" { char yych; - if (in.lim <= in.cur) if (fill(in, 1) != 0) return -1; - yych = *in.cur; + if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1; + yych = *in->cur; switch (yych) { case 0x00: goto yy1; case ' ': goto yy3; @@ -63,22 +63,22 @@ static int lex(Input &in) { default: goto yy2; } yy1: - ++in.cur; + ++in->cur; #line 57 "c/fill/02_fill.re" { // Check that it is the sentinel, not some unexpected null. - return in.tok == in.lim - YYMAXFILL ? count : -1; + return in->tok == in->lim - YYMAXFILL ? count : -1; } #line 73 "c/fill/02_fill.c" yy2: - ++in.cur; + ++in->cur; #line 63 "c/fill/02_fill.re" { return -1; } #line 78 "c/fill/02_fill.c" yy3: - ++in.cur; - if (in.lim <= in.cur) if (fill(in, 1) != 0) return -1; - yych = *in.cur; + ++in->cur; + if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1; + yych = *in->cur; switch (yych) { case ' ': goto yy3; default: goto yy4; @@ -88,22 +88,22 @@ static int lex(Input &in) { { goto loop; } #line 90 "c/fill/02_fill.c" yy5: - ++in.cur; - if (in.lim <= in.cur) if (fill(in, 1) != 0) return -1; - yych = *in.cur; + ++in->cur; + if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1; + yych = *in->cur; switch (yych) { case '\'': goto yy6; case '\\': goto yy7; default: goto yy5; } yy6: - ++in.cur; + ++in->cur; #line 61 "c/fill/02_fill.re" { ++count; goto loop; } #line 104 "c/fill/02_fill.c" yy7: - ++in.cur; - if (in.lim <= in.cur) if (fill(in, 1) != 0) return -1; + ++in->cur; + if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1; goto yy5; } #line 64 "c/fill/02_fill.re" @@ -124,14 +124,14 @@ int main() { int count = 3 * BUFSIZE; // number of quoted strings written to file // Initialize lexer state: all pointers are at the end of buffer. - // This immediately triggers YYFILL, as the check `in.cur < in.lim` fails. + // This immediately triggers YYFILL, as the check `in->cur < in->lim` fails. Input in; in.file = fopen(fname, "r"); in.cur = in.tok = in.lim = in.buf + BUFSIZE; in.eof = 0; // Run the lexer. - assert(lex(in) == count); + assert(lex(&in) == count); // Cleanup: remove input file. fclose(in.file); diff --git a/examples/c/fill/02_fill.re b/examples/c/fill/02_fill.re index 6a416603b..0008137bd 100644 --- a/examples/c/fill/02_fill.re +++ b/examples/c/fill/02_fill.re @@ -6,57 +6,57 @@ /*!max:re2c*/ #define BUFSIZE (4096 - YYMAXFILL) -struct Input { +typedef struct { FILE *file; char buf[BUFSIZE + YYMAXFILL], *lim, *cur, *tok; - bool eof; -}; + int eof; +} Input; -static int fill(Input &in, size_t need) { - if (in.eof) return 1; +static int fill(Input *in, size_t need) { + if (in->eof) return 1; - const size_t shift = in.tok - in.buf; - const size_t used = in.lim - in.tok; + const size_t shift = in->tok - in->buf; + const size_t used = in->lim - in->tok; // Error: lexeme too long. In real life could reallocate a larger buffer. if (shift < need) return 2; // Shift buffer contents (discard everything up to the current token). - memmove(in.buf, in.tok, used); - in.lim -= shift; - in.cur -= shift; - in.tok -= shift; + memmove(in->buf, in->tok, used); + in->lim -= shift; + in->cur -= shift; + in->tok -= shift; // Fill free space at the end of buffer with new data from file. - in.lim += fread(in.lim, 1, BUFSIZE - used, in.file); + in->lim += fread(in->lim, 1, BUFSIZE - used, in->file); // If read less than expected, this is end of input => add zero padding // so that the lexer can access characters at the end of buffer. - if (in.lim < in.buf + BUFSIZE) { - in.eof = true; - memset(in.lim, 0, YYMAXFILL); - in.lim += YYMAXFILL; + if (in->lim < in->buf + BUFSIZE) { + in->eof = 1; + memset(in->lim, 0, YYMAXFILL); + in->lim += YYMAXFILL; } return 0; } -static int lex(Input &in) { +static int lex(Input *in) { int count = 0; loop: - in.tok = in.cur; + in->tok = in->cur; /*!re2c re2c:api:style = free-form; re2c:define:YYCTYPE = char; - re2c:define:YYCURSOR = in.cur; - re2c:define:YYLIMIT = in.lim; + re2c:define:YYCURSOR = in->cur; + re2c:define:YYLIMIT = in->lim; re2c:define:YYFILL = "if (fill(in, @@) != 0) return -1;"; str = ['] ([^'\\] | [\\][^])* [']; [\x00] { // Check that it is the sentinel, not some unexpected null. - return in.tok == in.lim - YYMAXFILL ? count : -1; + return in->tok == in->lim - YYMAXFILL ? count : -1; } str { ++count; goto loop; } [ ]+ { goto loop; } @@ -78,14 +78,14 @@ int main() { int count = 3 * BUFSIZE; // number of quoted strings written to file // Initialize lexer state: all pointers are at the end of buffer. - // This immediately triggers YYFILL, as the check `in.cur < in.lim` fails. + // This immediately triggers YYFILL, as the check `in->cur < in->lim` fails. Input in; in.file = fopen(fname, "r"); in.cur = in.tok = in.lim = in.buf + BUFSIZE; in.eof = 0; // Run the lexer. - assert(lex(in) == count); + assert(lex(&in) == count); // Cleanup: remove input file. fclose(in.file); diff --git a/examples/c/headers/header.c b/examples/c/headers/header.c index a3eefc7bd..3ce0d6a70 100644 --- a/examples/c/headers/header.c +++ b/examples/c/headers/header.c @@ -6,30 +6,30 @@ -long lex(LexerState& st) { +long lex(LexerState* st) { const char *t; { char yych; goto yy0; yy1: - ++st.cur; + ++st->cur; yy0: - yych = *st.cur; + yych = *st->cur; switch (yych) { case 'a': goto yy1; case 'b': - st.yyt1 = st.cur; + st->yyt1 = st->cur; goto yy3; default: - st.yyt1 = st.cur; + st->yyt1 = st->cur; goto yy2; } yy2: - t = st.yyt1; - { return t - st.str; } + t = st->yyt1; + { return t - st->str; } yy3: - yych = *++st.cur; + yych = *++st->cur; switch (yych) { case 'b': goto yy3; default: goto yy2; @@ -41,13 +41,13 @@ long lex(LexerState& st) { int main() { const char *s = "ab"; LexerState st = { s, s , NULL }; - assert(lex(st) == 1); + assert(lex(&st) == 1); return 0; } /* Generated by re2c */ -struct LexerState { +typedef struct { const char *str, *cur; const char *yyt1; -}; +} LexerState; c/headers/header.re:23:21: warning: rule matches empty string [-Wmatch-empty-string] diff --git a/examples/c/headers/header.re b/examples/c/headers/header.re index f8dcac06a..9156684b0 100644 --- a/examples/c/headers/header.re +++ b/examples/c/headers/header.re @@ -4,29 +4,29 @@ #include "lexer/state.h" // the header is generated by re2c /*!header:re2c:on*/ -struct LexerState { +typedef struct { const char *str, *cur; /*!stags:re2c format = "const char *@@;"; */ -}; +} LexerState; /*!header:re2c:off*/ -long lex(LexerState& st) { +long lex(LexerState* st) { const char *t; /*!re2c re2c:header = "lexer/state.h"; re2c:yyfill:enable = 0; re2c:define:YYCTYPE = char; - re2c:define:YYCURSOR = "st.cur"; + re2c:define:YYCURSOR = "st->cur"; re2c:tags = 1; - re2c:tags:expression = "st.@@"; + re2c:tags:expression = "st->@@"; - [a]* @t [b]* { return t - st.str; } + [a]* @t [b]* { return t - st->str; } */ } int main() { const char *s = "ab"; LexerState st = { s, s /*!stags:re2c format = ", NULL"; */ }; - assert(lex(st) == 1); + assert(lex(&st) == 1); return 0; } diff --git a/examples/c/headers/lexer/state.h b/examples/c/headers/lexer/state.h index 9b204968c..5d87fc2da 100644 --- a/examples/c/headers/lexer/state.h +++ b/examples/c/headers/lexer/state.h @@ -1,8 +1,6 @@ /* Generated by re2c */ - typedef struct { const char *str, *cur; const char *yyt1; } LexerState; - diff --git a/examples/c/reuse/usedir.c b/examples/c/reuse/usedir.c index 02278fcbd..3233b18dd 100644 --- a/examples/c/reuse/usedir.c +++ b/examples/c/reuse/usedir.c @@ -9,7 +9,7 @@ // earlier. Default rule * occurs in all three blocks; the local (not // inherited) definition takes priority. -enum What { COLOR, FISH, DUNNO }; +typedef enum { COLOR, FISH, DUNNO } What; #line 15 "c/reuse/usedir.re" diff --git a/examples/c/reuse/usedir.re b/examples/c/reuse/usedir.re index 61bb9776d..5e6434260 100644 --- a/examples/c/reuse/usedir.re +++ b/examples/c/reuse/usedir.re @@ -7,7 +7,7 @@ // earlier. Default rule * occurs in all three blocks; the local (not // inherited) definition takes priority. -enum What { COLOR, FISH, DUNNO }; +typedef enum { COLOR, FISH, DUNNO } What; /*!rules:re2c:colors * { assert(false); } diff --git a/examples/c/state/push.c b/examples/c/state/push.c index d6f87a789..c3832b115 100644 --- a/examples/c/state/push.c +++ b/examples/c/state/push.c @@ -12,50 +12,50 @@ // In real world use a larger buffer. #define BUFSIZE 10 -struct State { +typedef struct { FILE *file; char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; int state; -}; +} State; typedef enum {END, READY, WAITING, BAD_PACKET, BIG_PACKET} Status; -static Status fill(State &st) { - const size_t shift = st.tok - st.buf; - const size_t used = st.lim - st.tok; +static Status fill(State *st) { + const size_t shift = st->tok - st->buf; + const size_t used = st->lim - st->tok; const size_t free = BUFSIZE - used; // Error: no space. In real life can reallocate a larger buffer. if (free < 1) return BIG_PACKET; // Shift buffer contents (discard already processed data). - memmove(st.buf, st.tok, used); - st.lim -= shift; - st.cur -= shift; - st.mar -= shift; - st.tok -= shift; + memmove(st->buf, st->tok, used); + st->lim -= shift; + st->cur -= shift; + st->mar -= shift; + st->tok -= shift; // Fill free space at the end of buffer with new data. - const size_t read = fread(st.lim, 1, free, st.file); - st.lim += read; - st.lim[0] = 0; // append sentinel symbol + const size_t read = fread(st->lim, 1, free, st->file); + st->lim += read; + st->lim[0] = 0; // append sentinel symbol return READY; } -static Status lex(State &st, unsigned int *recv) { +static Status lex(State *st, unsigned int *recv) { char yych; #line 50 "c/state/push.c" -switch (st.state) { +switch (st->state) { case 0: - if (st.lim <= st.cur) goto yy8; + if (st->lim <= st->cur) goto yy8; goto yyFillLabel0; case 1: - if (st.lim <= st.cur) goto yy3; + if (st->lim <= st->cur) goto yy3; goto yyFillLabel1; case 2: - if (st.lim <= st.cur) goto yy7; + if (st->lim <= st->cur) goto yy7; goto yyFillLabel2; default: goto yy0; } @@ -63,12 +63,12 @@ switch (st.state) { for (;;) { - st.tok = st.cur; + st->tok = st->cur; #line 69 "c/state/push.c" yy0: yyFillLabel0: - yych = *st.cur; + yych = *st->cur; switch (yych) { case 'a': case 'b': @@ -97,23 +97,23 @@ switch (st.state) { case 'y': case 'z': goto yy4; default: - if (st.lim <= st.cur) { - st.state = 0; + if (st->lim <= st->cur) { + st->state = 0; return WAITING; } goto yy2; } yy2: - ++st.cur; + ++st->cur; yy3: - st.state = -1; + st->state = -1; #line 63 "c/state/push.re" { return BAD_PACKET; } #line 113 "c/state/push.c" yy4: - st.mar = ++st.cur; + st->mar = ++st->cur; yyFillLabel1: - yych = *st.cur; + yych = *st->cur; switch (yych) { case ';': goto yy5; case 'a': @@ -143,22 +143,22 @@ switch (st.state) { case 'y': case 'z': goto yy6; default: - if (st.lim <= st.cur) { - st.state = 1; + if (st->lim <= st->cur) { + st->state = 1; return WAITING; } goto yy3; } yy5: - ++st.cur; - st.state = -1; + ++st->cur; + st->state = -1; #line 65 "c/state/push.re" { *recv = *recv + 1; continue; } #line 158 "c/state/push.c" yy6: - ++st.cur; + ++st->cur; yyFillLabel2: - yych = *st.cur; + yych = *st->cur; switch (yych) { case ';': goto yy5; case 'a': @@ -188,17 +188,17 @@ switch (st.state) { case 'y': case 'z': goto yy6; default: - if (st.lim <= st.cur) { - st.state = 2; + if (st->lim <= st->cur) { + st->state = 2; return WAITING; } goto yy7; } yy7: - st.cur = st.mar; + st->cur = st->mar; goto yy3; yy8: - st.state = -1; + st->state = -1; #line 64 "c/state/push.re" { return END; } #line 205 "c/state/push.c" @@ -230,7 +230,7 @@ void test(const char **packets, Status expect) { Status status; unsigned int send = 0, recv = 0; for (;;) { - status = lex(st, &recv); + status = lex(&st, &recv); if (status == END) { LOG("done: got %u packets\n", recv); break; @@ -241,7 +241,7 @@ void test(const char **packets, Status expect) { fprintf(fw, "%s", *packets++); ++send; } - status = fill(st); + status = fill(&st); LOG("queue: '%s'\n", st.buf); if (status == BIG_PACKET) { LOG("error: packet too big\n"); diff --git a/examples/c/state/push.re b/examples/c/state/push.re index e8f74c757..a53785ee0 100644 --- a/examples/c/state/push.re +++ b/examples/c/state/push.re @@ -10,51 +10,51 @@ // In real world use a larger buffer. #define BUFSIZE 10 -struct State { +typedef struct { FILE *file; char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; int state; -}; +} State; typedef enum {END, READY, WAITING, BAD_PACKET, BIG_PACKET} Status; -static Status fill(State &st) { - const size_t shift = st.tok - st.buf; - const size_t used = st.lim - st.tok; +static Status fill(State *st) { + const size_t shift = st->tok - st->buf; + const size_t used = st->lim - st->tok; const size_t free = BUFSIZE - used; // Error: no space. In real life can reallocate a larger buffer. if (free < 1) return BIG_PACKET; // Shift buffer contents (discard already processed data). - memmove(st.buf, st.tok, used); - st.lim -= shift; - st.cur -= shift; - st.mar -= shift; - st.tok -= shift; + memmove(st->buf, st->tok, used); + st->lim -= shift; + st->cur -= shift; + st->mar -= shift; + st->tok -= shift; // Fill free space at the end of buffer with new data. - const size_t read = fread(st.lim, 1, free, st.file); - st.lim += read; - st.lim[0] = 0; // append sentinel symbol + const size_t read = fread(st->lim, 1, free, st->file); + st->lim += read; + st->lim[0] = 0; // append sentinel symbol return READY; } -static Status lex(State &st, unsigned int *recv) { +static Status lex(State *st, unsigned int *recv) { char yych; /*!getstate:re2c*/ for (;;) { - st.tok = st.cur; + st->tok = st->cur; /*!re2c re2c:api:style = free-form; re2c:define:YYCTYPE = "char"; - re2c:define:YYCURSOR = "st.cur"; - re2c:define:YYMARKER = "st.mar"; - re2c:define:YYLIMIT = "st.lim"; - re2c:define:YYGETSTATE = "st.state"; - re2c:define:YYSETSTATE = "st.state = @@;"; + re2c:define:YYCURSOR = "st->cur"; + re2c:define:YYMARKER = "st->mar"; + re2c:define:YYLIMIT = "st->lim"; + re2c:define:YYGETSTATE = "st->state"; + re2c:define:YYSETSTATE = "st->state = @@;"; re2c:define:YYFILL = "return WAITING;"; re2c:eof = 0; @@ -90,7 +90,7 @@ void test(const char **packets, Status expect) { Status status; unsigned int send = 0, recv = 0; for (;;) { - status = lex(st, &recv); + status = lex(&st, &recv); if (status == END) { LOG("done: got %u packets\n", recv); break; @@ -101,7 +101,7 @@ void test(const char **packets, Status expect) { fprintf(fw, "%s", *packets++); ++send; } - status = fill(st); + status = fill(&st); LOG("queue: '%s'\n", st.buf); if (status == BIG_PACKET) { LOG("error: packet too big\n"); diff --git a/examples/c/submatch/01_stags.c b/examples/c/submatch/01_stags.c index 78cfc2c07..4b8b2486f 100644 --- a/examples/c/submatch/01_stags.c +++ b/examples/c/submatch/01_stags.c @@ -4,7 +4,7 @@ #include #include -struct SemVer { int major, minor, patch; }; +typedef struct { int major, minor, patch; } SemVer; static int s2n(const char *s, const char *e) { // pre-parsed string to number int n = 0; @@ -12,7 +12,7 @@ static int s2n(const char *s, const char *e) { // pre-parsed string to number return n; } -static bool lex(const char *str, SemVer &ver) { +static int lex(const char *str, SemVer *ver) { const char *YYCURSOR = str, *YYMARKER; // User-defined tag variables that are available in semantic action. @@ -52,7 +52,7 @@ const char *yyt4; ++YYCURSOR; yy2: #line 35 "c/submatch/01_stags.re" - { return false; } + { return 1; } #line 57 "c/submatch/01_stags.c" yy3: yych = *(YYMARKER = ++YYCURSOR); @@ -138,10 +138,10 @@ const char *yyt4; t2 -= 1; #line 29 "c/submatch/01_stags.re" { - ver.major = s2n(t1, t2); - ver.minor = s2n(t3, t4); - ver.patch = t5 != NULL ? s2n(t5, YYCURSOR - 1) : 0; - return true; + ver->major = s2n(t1, t2); + ver->minor = s2n(t3, t4); + ver->patch = t5 != NULL ? s2n(t5, YYCURSOR - 1) : 0; + return 0; } #line 147 "c/submatch/01_stags.c" yy9: @@ -184,8 +184,8 @@ const char *yyt4; int main() { SemVer v; - assert(lex("23.34", v) && v.major == 23 && v.minor == 34 && v.patch == 0); - assert(lex("1.2.999", v) && v.major == 1 && v.minor == 2 && v.patch == 999); - assert(!lex("1.a", v)); + assert(lex("23.34", &v) == 0 && v.major == 23 && v.minor == 34 && v.patch == 0); + assert(lex("1.2.999", &v) == 0 && v.major == 1 && v.minor == 2 && v.patch == 999); + assert(lex("1.a", &v) == 1); return 0; } diff --git a/examples/c/submatch/01_stags.re b/examples/c/submatch/01_stags.re index 1c9a83857..238207a9c 100644 --- a/examples/c/submatch/01_stags.re +++ b/examples/c/submatch/01_stags.re @@ -2,7 +2,7 @@ #include #include -struct SemVer { int major, minor, patch; }; +typedef struct { int major, minor, patch; } SemVer; static int s2n(const char *s, const char *e) { // pre-parsed string to number int n = 0; @@ -10,7 +10,7 @@ static int s2n(const char *s, const char *e) { // pre-parsed string to number return n; } -static bool lex(const char *str, SemVer &ver) { +static int lex(const char *str, SemVer *ver) { const char *YYCURSOR = str, *YYMARKER; // User-defined tag variables that are available in semantic action. @@ -27,19 +27,19 @@ static bool lex(const char *str, SemVer &ver) { num = [0-9]+; @t1 num @t2 "." @t3 num @t4 ("." @t5 num)? [\x00] { - ver.major = s2n(t1, t2); - ver.minor = s2n(t3, t4); - ver.patch = t5 != NULL ? s2n(t5, YYCURSOR - 1) : 0; - return true; + ver->major = s2n(t1, t2); + ver->minor = s2n(t3, t4); + ver->patch = t5 != NULL ? s2n(t5, YYCURSOR - 1) : 0; + return 0; } - * { return false; } + * { return 1; } */ } int main() { SemVer v; - assert(lex("23.34", v) && v.major == 23 && v.minor == 34 && v.patch == 0); - assert(lex("1.2.999", v) && v.major == 1 && v.minor == 2 && v.patch == 999); - assert(!lex("1.a", v)); + assert(lex("23.34", &v) == 0 && v.major == 23 && v.minor == 34 && v.patch == 0); + assert(lex("1.2.999", &v) == 0 && v.major == 1 && v.minor == 2 && v.patch == 999); + assert(lex("1.a", &v) == 1); return 0; } diff --git a/examples/c/submatch/03_captures.c b/examples/c/submatch/03_captures.c index f65733a23..3421bbc5a 100644 --- a/examples/c/submatch/03_captures.c +++ b/examples/c/submatch/03_captures.c @@ -4,7 +4,7 @@ #include #include -struct SemVer { int major, minor, patch; }; +typedef struct { int major, minor, patch; } SemVer; static int s2n(const char *s, const char *e) { // pre-parsed string to number int n = 0; @@ -12,7 +12,7 @@ static int s2n(const char *s, const char *e) { // pre-parsed string to number return n; } -static bool lex(const char *str, SemVer &ver) { +static int lex(const char *str, SemVer *ver) { const char *YYCURSOR = str, *YYMARKER; // Final tag variables available in semantic action. @@ -64,7 +64,7 @@ const char *yyt5; ++YYCURSOR; yy2: #line 36 "c/submatch/03_captures.re" - { return false; } + { return 1; } #line 69 "c/submatch/03_captures.c" yy3: yych = *(YYMARKER = ++YYCURSOR); @@ -156,10 +156,10 @@ const char *yyt5; #line 29 "c/submatch/03_captures.re" { (void) yytl0; (void) yytr0; // some variables are unused - ver.major = s2n(yytl1, yytr1); - ver.minor = s2n(yytl2, yytr2); - ver.patch = yytl3 ? s2n(yytl3 + 1, yytr3) : 0; - return true; + ver->major = s2n(yytl1, yytr1); + ver->minor = s2n(yytl2, yytr2); + ver->patch = yytl3 ? s2n(yytl3 + 1, yytr3) : 0; + return 0; } #line 165 "c/submatch/03_captures.c" yy9: @@ -192,8 +192,8 @@ const char *yyt5; int main() { SemVer v; - assert(lex("23.34", v) && v.major == 23 && v.minor == 34 && v.patch == 0); - assert(lex("1.2.999", v) && v.major == 1 && v.minor == 2 && v.patch == 999); - assert(!lex("1.a", v)); + assert(lex("23.34", &v) == 0 && v.major == 23 && v.minor == 34 && v.patch == 0); + assert(lex("1.2.999", &v) == 0 && v.major == 1 && v.minor == 2 && v.patch == 999); + assert(lex("1.a", &v) == 1); return 0; } diff --git a/examples/c/submatch/03_captures.re b/examples/c/submatch/03_captures.re index e114a79c4..cdad3badd 100644 --- a/examples/c/submatch/03_captures.re +++ b/examples/c/submatch/03_captures.re @@ -2,7 +2,7 @@ #include #include -struct SemVer { int major, minor, patch; }; +typedef struct { int major, minor, patch; } SemVer; static int s2n(const char *s, const char *e) { // pre-parsed string to number int n = 0; @@ -10,7 +10,7 @@ static int s2n(const char *s, const char *e) { // pre-parsed string to number return n; } -static bool lex(const char *str, SemVer &ver) { +static int lex(const char *str, SemVer *ver) { const char *YYCURSOR = str, *YYMARKER; // Final tag variables available in semantic action. @@ -28,19 +28,19 @@ static bool lex(const char *str, SemVer &ver) { (num) "." (num) ("." num)? [\x00] { (void) yytl0; (void) yytr0; // some variables are unused - ver.major = s2n(yytl1, yytr1); - ver.minor = s2n(yytl2, yytr2); - ver.patch = yytl3 ? s2n(yytl3 + 1, yytr3) : 0; - return true; + ver->major = s2n(yytl1, yytr1); + ver->minor = s2n(yytl2, yytr2); + ver->patch = yytl3 ? s2n(yytl3 + 1, yytr3) : 0; + return 0; } - * { return false; } + * { return 1; } */ } int main() { SemVer v; - assert(lex("23.34", v) && v.major == 23 && v.minor == 34 && v.patch == 0); - assert(lex("1.2.999", v) && v.major == 1 && v.minor == 2 && v.patch == 999); - assert(!lex("1.a", v)); + assert(lex("23.34", &v) == 0 && v.major == 23 && v.minor == 34 && v.patch == 0); + assert(lex("1.2.999", &v) == 0 && v.major == 1 && v.minor == 2 && v.patch == 999); + assert(lex("1.a", &v) == 1); return 0; } diff --git a/examples/c/submatch/04_posix_captures.c b/examples/c/submatch/04_posix_captures.c index 83f2b34ef..d63925a45 100644 --- a/examples/c/submatch/04_posix_captures.c +++ b/examples/c/submatch/04_posix_captures.c @@ -10,7 +10,7 @@ #line 6 "c/submatch/04_posix_captures.re" -struct SemVer { int major, minor, patch; }; +typedef struct { int major, minor, patch; } SemVer; static int s2n(const char *s, const char *e) { // pre-parsed string to number int n = 0; @@ -18,7 +18,7 @@ static int s2n(const char *s, const char *e) { // pre-parsed string to number return n; } -static bool lex(const char *str, SemVer &ver) { +static int lex(const char *str, SemVer *ver) { const char *YYCURSOR = str, *YYMARKER; // Allocate memory for capturing parentheses (twice the number of groups). @@ -60,7 +60,7 @@ const char *yyt5; ++YYCURSOR; yy2: #line 43 "c/submatch/04_posix_captures.re" - { return false; } + { return 1; } #line 65 "c/submatch/04_posix_captures.c" yy3: yych = *(YYMARKER = ++YYCURSOR); @@ -156,10 +156,10 @@ const char *yyt5; assert(yynmatch == 4); // Even `yypmatch` values are for opening parentheses, odd values // are for closing parentheses, the first group is the whole match. - ver.major = s2n(yypmatch[2], yypmatch[3]); - ver.minor = s2n(yypmatch[4], yypmatch[5]); - ver.patch = yypmatch[6] ? s2n(yypmatch[6] + 1, yypmatch[7]) : 0; - return true; + ver->major = s2n(yypmatch[2], yypmatch[3]); + ver->minor = s2n(yypmatch[4], yypmatch[5]); + ver->patch = yypmatch[6] ? s2n(yypmatch[6] + 1, yypmatch[7]) : 0; + return 0; } #line 165 "c/submatch/04_posix_captures.c" yy9: @@ -192,8 +192,8 @@ const char *yyt5; int main() { SemVer v; - assert(lex("23.34", v) && v.major == 23 && v.minor == 34 && v.patch == 0); - assert(lex("1.2.999", v) && v.major == 1 && v.minor == 2 && v.patch == 999); - assert(!lex("1.a", v)); + assert(lex("23.34", &v) == 0 && v.major == 23 && v.minor == 34 && v.patch == 0); + assert(lex("1.2.999", &v) == 0 && v.major == 1 && v.minor == 2 && v.patch == 999); + assert(lex("1.a", &v) == 1); return 0; } diff --git a/examples/c/submatch/04_posix_captures.re b/examples/c/submatch/04_posix_captures.re index a3311e83d..e8de3876d 100644 --- a/examples/c/submatch/04_posix_captures.re +++ b/examples/c/submatch/04_posix_captures.re @@ -5,7 +5,7 @@ // Maximum number of capturing groups among all rules. /*!maxnmatch:re2c*/ -struct SemVer { int major, minor, patch; }; +typedef struct { int major, minor, patch; } SemVer; static int s2n(const char *s, const char *e) { // pre-parsed string to number int n = 0; @@ -13,7 +13,7 @@ static int s2n(const char *s, const char *e) { // pre-parsed string to number return n; } -static bool lex(const char *str, SemVer &ver) { +static int lex(const char *str, SemVer *ver) { const char *YYCURSOR = str, *YYMARKER; // Allocate memory for capturing parentheses (twice the number of groups). @@ -35,19 +35,19 @@ static bool lex(const char *str, SemVer &ver) { assert(yynmatch == 4); // Even `yypmatch` values are for opening parentheses, odd values // are for closing parentheses, the first group is the whole match. - ver.major = s2n(yypmatch[2], yypmatch[3]); - ver.minor = s2n(yypmatch[4], yypmatch[5]); - ver.patch = yypmatch[6] ? s2n(yypmatch[6] + 1, yypmatch[7]) : 0; - return true; + ver->major = s2n(yypmatch[2], yypmatch[3]); + ver->minor = s2n(yypmatch[4], yypmatch[5]); + ver->patch = yypmatch[6] ? s2n(yypmatch[6] + 1, yypmatch[7]) : 0; + return 0; } - * { return false; } + * { return 1; } */ } int main() { SemVer v; - assert(lex("23.34", v) && v.major == 23 && v.minor == 34 && v.patch == 0); - assert(lex("1.2.999", v) && v.major == 1 && v.minor == 2 && v.patch == 999); - assert(!lex("1.a", v)); + assert(lex("23.34", &v) == 0 && v.major == 23 && v.minor == 34 && v.patch == 0); + assert(lex("1.2.999", &v) == 0 && v.major == 1 && v.minor == 2 && v.patch == 999); + assert(lex("1.a", &v) == 1); return 0; }