Fix handling of the SV `` delimiter when combined with macro usage.
Given a macro definition like this: `define name `macro``text the preprocessor should expand `macro, not `macrotext, when it expands `name. This also ensures that `define name(p,s) p``_``s `define PREFIX my_prefix `define SUFFIX my_suffix `name(`PREFIX, `SUFFIX) expands to my_prefix_my_suffix as the user would expect.
This commit is contained in:
parent
dc2aa6efa0
commit
d8556e4c86
126
ivlpp/lexor.lex
126
ivlpp/lexor.lex
|
|
@ -154,11 +154,13 @@ static void ifdef_leave(void)
|
|||
result = (rc == 0) ? YY_NULL : rc; \
|
||||
} else { \
|
||||
/* We are expanding a macro. Handle the SV `` delimiter. \
|
||||
There doesn't seem to be any good reason not to allow \
|
||||
it in traditional Verilog as well. */ \
|
||||
while ((istack->str[0] == '`') && \
|
||||
(istack->str[1] == '`')) { \
|
||||
istack->str += 2; \
|
||||
If the delimiter terminates a compiler directive, leave \
|
||||
it in place, otherwise remove it now. */ \
|
||||
if (yytext[0] != '`') { \
|
||||
while ((istack->str[0] == '`') && \
|
||||
(istack->str[1] == '`')) { \
|
||||
istack->str += 2; \
|
||||
} \
|
||||
} \
|
||||
if (*istack->str == 0) { \
|
||||
result = YY_NULL; \
|
||||
|
|
@ -172,12 +174,12 @@ static void ifdef_leave(void)
|
|||
static int comment_enter = 0;
|
||||
static int pragma_enter = 0;
|
||||
static int string_enter = 0;
|
||||
static int prev_state = 0;
|
||||
|
||||
static int ma_parenthesis_level = 0;
|
||||
%}
|
||||
|
||||
%option stack
|
||||
%option nounput
|
||||
%option noinput
|
||||
%option noyy_top_state
|
||||
%option noyywrap
|
||||
|
|
@ -195,6 +197,11 @@ static int ma_parenthesis_level = 0;
|
|||
%x CSTRING
|
||||
%x ERROR_LINE
|
||||
|
||||
%x IFDEF_NAME
|
||||
%x IFNDEF_NAME
|
||||
%x ELSIF_NAME
|
||||
%x ELSIF_SUPR
|
||||
|
||||
%x IFDEF_FALSE
|
||||
%s IFDEF_TRUE
|
||||
%x IFDEF_SUPR
|
||||
|
|
@ -392,56 +399,51 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
|||
* condition that stacks on top of the IFDEF_FALSE so that output is
|
||||
* not accidentally turned on within nested ifdefs.
|
||||
*/
|
||||
`ifdef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
char* name = strchr(yytext, '`'); assert(name);
|
||||
|
||||
name += 6;
|
||||
name += strspn(name, " \t\b\f");
|
||||
|
||||
`ifdef{W} {
|
||||
ifdef_enter();
|
||||
|
||||
if (is_defined(name))
|
||||
yy_push_state(IFDEF_TRUE);
|
||||
else
|
||||
yy_push_state(IFDEF_FALSE);
|
||||
yy_push_state(IFDEF_NAME);
|
||||
}
|
||||
|
||||
`ifndef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
char* name = strchr(yytext, '`'); assert(name);
|
||||
|
||||
name += 7;
|
||||
name += strspn(name, " \t\b\f");
|
||||
|
||||
`ifndef{W} {
|
||||
ifdef_enter();
|
||||
|
||||
if (!is_defined(name))
|
||||
yy_push_state(IFDEF_TRUE);
|
||||
else
|
||||
yy_push_state(IFDEF_FALSE);
|
||||
yy_push_state(IFNDEF_NAME);
|
||||
}
|
||||
|
||||
<IFDEF_FALSE,IFDEF_SUPR>`ifdef{W} |
|
||||
<IFDEF_FALSE,IFDEF_SUPR>`ifndef{W} { ifdef_enter(); yy_push_state(IFDEF_SUPR); }
|
||||
|
||||
<IFDEF_TRUE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* { BEGIN(IFDEF_SUPR); }
|
||||
<IFDEF_TRUE>`elsif{W} { prev_state = YYSTATE; BEGIN(ELSIF_SUPR); }
|
||||
<IFDEF_FALSE>`elsif{W} { prev_state = YYSTATE; BEGIN(ELSIF_NAME); }
|
||||
<IFDEF_SUPR>`elsif{W} { prev_state = YYSTATE; BEGIN(ELSIF_SUPR); }
|
||||
|
||||
<IFDEF_FALSE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
char* name = strchr(yytext, '`'); assert(name);
|
||||
<IFDEF_TRUE>`else { BEGIN(IFDEF_SUPR); }
|
||||
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
|
||||
<IFDEF_SUPR>`else {}
|
||||
|
||||
name += 6;
|
||||
name += strspn(name, " \t\b\f");
|
||||
|
||||
if (is_defined(name))
|
||||
<IFDEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
if (is_defined(yytext))
|
||||
BEGIN(IFDEF_TRUE);
|
||||
else
|
||||
BEGIN(IFDEF_FALSE);
|
||||
}
|
||||
|
||||
<IFDEF_SUPR>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* { }
|
||||
<IFNDEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
if (!is_defined(yytext))
|
||||
BEGIN(IFDEF_TRUE);
|
||||
else
|
||||
BEGIN(IFDEF_FALSE);
|
||||
}
|
||||
|
||||
<IFDEF_TRUE>`else { BEGIN(IFDEF_SUPR); }
|
||||
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
|
||||
<IFDEF_SUPR>`else {}
|
||||
<ELSIF_NAME>[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
if (is_defined(yytext))
|
||||
BEGIN(IFDEF_TRUE);
|
||||
else
|
||||
BEGIN(IFDEF_FALSE);
|
||||
}
|
||||
|
||||
<ELSIF_SUPR>[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
BEGIN(IFDEF_SUPR);
|
||||
}
|
||||
|
||||
<IFDEF_FALSE,IFDEF_SUPR>"//"[^\r\n]* {}
|
||||
|
||||
|
|
@ -462,25 +464,45 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
|||
|
||||
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif { ifdef_leave(); yy_pop_state(); }
|
||||
|
||||
<IFDEF_NAME>(\n|\r) |
|
||||
<IFDEF_NAME>. |
|
||||
`ifdef {
|
||||
error_count += 1;
|
||||
fprintf(stderr, "%s:%u: `ifdef without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
if (YY_START == IFDEF_NAME) {
|
||||
ifdef_leave();
|
||||
yy_pop_state();
|
||||
unput(yytext[0]);
|
||||
}
|
||||
}
|
||||
|
||||
<IFNDEF_NAME>(\n|\r) |
|
||||
<IFNDEF_NAME>. |
|
||||
`ifndef {
|
||||
error_count += 1;
|
||||
fprintf(stderr, "%s:%u: `ifndef without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
if (YY_START == IFNDEF_NAME) {
|
||||
ifdef_leave();
|
||||
yy_pop_state();
|
||||
unput(yytext[0]);
|
||||
}
|
||||
}
|
||||
|
||||
<ELSIF_NAME,ELSIF_SUPR>(\n|\r) |
|
||||
<ELSIF_NAME,ELSIF_SUPR>. |
|
||||
`elsif {
|
||||
error_count += 1;
|
||||
fprintf(stderr, "%s:%u: `elsif without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
if (YY_START != INITIAL) {
|
||||
BEGIN(prev_state);
|
||||
unput(yytext[0]);
|
||||
}
|
||||
}
|
||||
|
||||
`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
<INITIAL>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
error_count += 1;
|
||||
fprintf(stderr, "%s:%u: `elsif without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
|
|
@ -516,16 +538,24 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
|||
/* Stringified version of macro expansion. This is an Icarus extension.
|
||||
When expanding macro text, the SV usage of `` takes precedence. */
|
||||
``[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
assert(istack->file);
|
||||
assert(do_expand_stringify_flag == 0);
|
||||
do_expand_stringify_flag = 1;
|
||||
fputc('"', yyout);
|
||||
if (macro_needs_args(yytext+2))
|
||||
yy_push_state(MA_START);
|
||||
else
|
||||
do_expand(0);
|
||||
if (istack->file) {
|
||||
assert(do_expand_stringify_flag == 0);
|
||||
do_expand_stringify_flag = 1;
|
||||
fputc('"', yyout);
|
||||
if (macro_needs_args(yytext+2))
|
||||
yy_push_state(MA_START);
|
||||
else
|
||||
do_expand(0);
|
||||
} else {
|
||||
REJECT;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we are expanding a macro, remove the SV `` delimiter, otherwise
|
||||
* leave it to be handled by the normal rules.
|
||||
*/
|
||||
`` { if (istack->file) REJECT; }
|
||||
|
||||
/* If we are expanding a macro, handle the SV `" override. This avoids
|
||||
* entering CSTRING state, thus allowing nested macro expansions.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue