Skip to content

Condition switch generated for only one lexer per file #295

@pwnalone

Description

@pwnalone

Example

#include <assert.h>
#include <string.h>


/*!types:re2c */

int lex_char(const char* cur, const char* lim)
{
    int condition = yycinit;
    const char* mrk;

    char yych;

    /*!re2c
        re2c:define:YYCTYPE = char;
        re2c:define:YYLIMIT  = lim;
        re2c:define:YYCURSOR = cur;
        re2c:define:YYMARKER = mrk;
        re2c:yych:emit = 0;
        re2c:define:YYGETCONDITION = 'condition';
        re2c:define:YYGETCONDITION:naked = 1;
        re2c:define:YYSETCONDITION = 'condition = @@;';
        re2c:define:YYSETCONDITION:naked = 1;
        re2c:yyfill:enable = 0;

        <init> "\\"         { return -1; }

        <init> "\\f"        { yych = '\f'; goto done; }
        <init> "\\n"        { yych = '\n'; goto done; }
        <init> "\\r"        { yych = '\r'; goto done; }
        <init> "\\t"        { yych = '\t'; goto done; }
        <init> "\\v"        { yych = '\v'; goto done; }

        <init> *            { goto done; }
    */

done:
    return cur == lim ? yych : -1;
}

int lex(const char* cur)
{
    const char* lim;
    const char* mrk;

    char yych;

    int condition = yycinit;

    lim = cur + strlen(cur);
loop:
    mrk = cur;

    /*!re2c
        re2c:define:YYCTYPE = char;
        re2c:define:YYLIMIT  = lim;
        re2c:define:YYCURSOR = cur;
        re2c:define:YYMARKER = mrk;
        re2c:yych:emit = 0;
        re2c:define:YYGETCONDITION = 'condition';
        re2c:define:YYGETCONDITION:naked = 1;
        re2c:define:YYSETCONDITION = 'condition = @@;';
        re2c:define:YYSETCONDITION:naked = 1;
        re2c:yyfill:enable = 0;
        re2c:eof = 0;

        <init> *                                        { return -1; }
        <init> $                                        { return  0; }

        <init> [/][/] .*                                { goto loop; }
        <init> [/][*]                   => comment      { goto loop; }

        <init> [ \t]+                                   { goto loop; }

        <init, comment> [\n]+                           { goto loop; }

        <comment> [^*\n]+ [*]*          => comment      { goto loop; }
        <comment> [^*\n]* [*]+          => comment      { goto loop; }
        <comment> [^*\n]* [*]+ [/]      => init         { goto loop; }

        <comment> *                     => comment      { goto loop; }
        <comment> $                                     { return -1; }

        <init> ['] ([\\][^\n] | [^'\n])+ [']            {
            int chr = lex_char(mrk + 1, cur - 1);
            if (chr < 0) {
                return -1;
            } else {
                goto loop;
            }
            }
    */
}


int main(void)
{
    assert(!lex("/* hello, */ '\\n' // world !"));

    return 0;
}

Compile & Run

re2c -W -Werror -c -o bug.c bug.re && gcc -o bug bug.c && ./bug

Description

The above code should be fine, but rather the assert() fails because no switch-statement is generated for the condition variable in lex(). There is only one switch-statement, shown below, that is generated for the first lexer (i.e. the sub-lexer in lex_char()), but there should be another one generated in lex() with the additional yyccomment case.

switch (condition) {
case yycinit:
    goto yyc_init;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions