preprocessor: add @#ifndef directive

time-shift
Houtan Bastani 2012-06-26 15:12:31 +02:00
parent ebc7a783bd
commit 20f2c1760b
5 changed files with 44 additions and 8 deletions

View File

@ -6540,8 +6540,8 @@ line. The main directives are:
@item
@code{@@#define}, for defining a macro-processor variable,
@item
@code{@@#if}, @code{@@#ifdef}, @code{@@#else}, @code{@@#endif} for
conditional statements,
@code{@@#if}, @code{@@#ifdef}, @code{@@#ifndef}, @code{@@#else},
@code{@@#endif} for conditional statements,
@item
@code{@@#for}, @code{@@#endfor} for constructing loops.
@end itemize
@ -6684,10 +6684,11 @@ end;
@deffn {Macro directive} @@#if @var{MACRO_EXPRESSION}
@deffnx {Macro directive} @@#ifdef @var{MACRO_VARIABLE}
@deffnx {Macro directive} @@#ifndef @var{MACRO_VARIABLE}
@deffnx {Macro directive} @@#else
@deffnx {Macro directive} @@#endif
Conditional inclusion of some part of the @file{.mod} file.
The lines between @code{@@#if} or @code{@@#ifdef} and the next
The lines between @code{@@#if}, @code{@@#ifdef} or @code{@@#ifndef} and the next
@code{@@#else} or @code{@@#endif} is executed only if the condition
evaluates to a non-null integer. The @code{@@#else} branch is optional
and, if present, is only evaluated if the condition evaluates to
@ -6726,6 +6727,21 @@ model;
end;
@end example
Choose between two alternative monetary policy rules using a
macro-variable. As @code{linear_mon_pol} was not previously defined in
this example, the first equation will be chosen:
@example
model;
@@#ifndef linear_mon_pol
i = w*i(-1) + (1-w)*i_ss + w2*(pie-piestar);
@@#else
i = i(-1)^w * i_ss^(1-w) * (pie/piestar)^w2;
@@#endif
...
end;
@end example
@end deffn
@deffn {Macro directive} @@#for @var{MACRO_VARIABLE} in @var{MACRO_EXPRESSION}

View File

@ -79,7 +79,7 @@ class MacroDriver;
%}
%token DEFINE LINE FOR IN IF ELSE ENDIF ECHO_DIR ERROR IFDEF
%token DEFINE LINE FOR IN IF ELSE ENDIF ECHO_DIR ERROR IFDEF IFNDEF
%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL
%token <int_val> INTEGER
@ -119,6 +119,8 @@ statement : expr
{ TYPERR_CATCH(driver.begin_if($2), @$); }
| IFDEF NAME
{ TYPERR_CATCH(driver.begin_ifdef(*$2), @$); delete $2; }
| IFNDEF NAME
{ TYPERR_CATCH(driver.begin_ifndef(*$2), @$); delete $2; }
| ECHO_DIR expr
{ TYPERR_CATCH(driver.echo(@$, $2), @$); }
| ERROR expr

View File

@ -178,6 +178,20 @@ MacroDriver::begin_ifdef(const string &name)
}
}
void
MacroDriver::begin_ifndef(const string &name)
{
try
{
get_variable(name);
begin_if(new IntMV(*this, 0));
}
catch (UnknownVariable &)
{
begin_if(new IntMV(*this, 1));
}
}
void
MacroDriver::echo(const Macro::parser::location_type &l, const MacroValue *value) const throw (MacroValue::TypeError)
{

View File

@ -211,6 +211,9 @@ public:
//! Begins an @#ifdef statement
void begin_ifdef(const string &name);
//! Begins an @#ifndef statement
void begin_ifndef(const string &name);
//! Executes @#echo directive
void echo(const Macro::parser::location_type &l, const MacroValue *value) const throw (MacroValue::TypeError);

View File

@ -165,10 +165,11 @@ CONT \\\\
<STMT>endfor { driver.error(*yylloc, "@#endfor is not matched by a @#for statement"); }
<STMT>ifdef { reading_if_statement = true; return token::IFDEF; }
<STMT>ifndef { reading_if_statement = true; return token::IFNDEF; }
<STMT>if { reading_if_statement = true; return token::IF; }
<STMT>else { driver.error(*yylloc, "@#else is not matched by an @#if/@#ifdef statement"); }
<STMT>endif { driver.error(*yylloc, "@#endif is not matched by an @#if/@#ifdef statement"); }
<STMT>else { driver.error(*yylloc, "@#else is not matched by an @#if/@#ifdef/@#ifndef statement"); }
<STMT>endif { driver.error(*yylloc, "@#endif is not matched by an @#if/@#ifdef/@#ifndef statement"); }
<STMT>echo { return token::ECHO_DIR; }
<STMT>error { return token::ERROR; }
@ -225,7 +226,7 @@ CONT \\\\
yylloc->step();
}
<THEN_BODY>. { then_body_tmp.append(yytext); yylloc->step(); }
<THEN_BODY><<EOF>> { driver.error(if_stmt_loc_tmp, "@#if/@#ifdef not matched by an @#endif (unexpected end of file)"); }
<THEN_BODY><<EOF>> { driver.error(if_stmt_loc_tmp, "@#if/@#ifdef/@#ifndef not matched by an @#endif (unexpected end of file)"); }
<THEN_BODY>^{SPC}*@#{SPC}*else{SPC}*(\/\/.*)?{EOL} {
yylloc->lines(1);
yylloc->step();
@ -267,7 +268,7 @@ CONT \\\\
yylloc->step();
}
<ELSE_BODY>. { else_body_tmp.append(yytext); yylloc->step(); }
<ELSE_BODY><<EOF>> { driver.error(if_stmt_loc_tmp, "@#if/@#ifdef not matched by an @#endif (unexpected end of file)"); }
<ELSE_BODY><<EOF>> { driver.error(if_stmt_loc_tmp, "@#if/@#ifdef/@#ifndef not matched by an @#endif (unexpected end of file)"); }
<ELSE_BODY>^{SPC}*@#{SPC}*endif{SPC}*(\/\/.*)?{EOL} {
yylloc->lines(1);