Skip to content
Snippets Groups Projects
Verified Commit 1de34765 authored by Sébastien Villemot's avatar Sébastien Villemot
Browse files

Macroprocessor: fix line counter inside @{} constructs

There were two bugs:
– with the LF convention, newlines were counted twice
– with the CR+LF convention, they were counted four times (because the CR was
  included in yyleng, alongside the LF)

The fix consists in implementing a location_increment() method similar to the
one used for the Dynare parser. This is the most robust solution.

By the way, mark the method DynareFlex::location_increment() method static.
parent 487c3729
No related branches found
No related tags found
No related merge requests found
......@@ -75,7 +75,7 @@ public:
string filename;
//! Increment the location counter given a token
void location_increment(Dynare::parser::location_type *yylloc, const char *yytext);
static void location_increment(Dynare::parser::location_type *yylloc, const char *yytext);
//! Count parens in dates statement
int dates_parens_nb;
......
/*
* Copyright © 2019-2020 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
......@@ -56,6 +56,7 @@ namespace macro
Tokenizer::parser::token_type lex(Tokenizer::parser::semantic_type *yylval,
Tokenizer::parser::location_type *yylloc,
macro::Driver &driver);
static void location_increment(Tokenizer::parser::location_type *yylloc, const char *yytext);
};
//! Implements the macro expansion using a Flex scanner and a Bison parser
......
......@@ -50,7 +50,7 @@ using token = Tokenizer::parser::token;
%{
// Increments location counter for every token read
# define YY_USER_ACTION yylloc->columns(yyleng);
#define YY_USER_ACTION location_increment(yylloc, yytext);
%}
SPC [ \t]+
......@@ -175,22 +175,15 @@ CONT \\\\{SPC}*
}
<expr,eval>{SPC}+ { }
<eval>{EOL}+ { yylloc->lines(yyleng); yylloc->lines(yyleng); }
<eval>{EOL}+ { }
<eval>\} { BEGIN(INITIAL); return token::END_EVAL; }
<expr,end_line>{CONT}("//".*)?{SPC}*{EOL} { yylloc->lines(1); yylloc->step(); }
<expr,end_line>{SPC}*("//".*)?{EOL} {
yylloc->lines(1);
BEGIN(INITIAL);
return token::EOL;
}
<expr,end_line>{CONT}("//".*)?{SPC}*{EOL} { yylloc->step(); }
<expr,end_line>{SPC}*("//".*)?{EOL} { BEGIN(INITIAL); return token::EOL; }
<INITIAL>^{SPC}*@#{SPC}* { BEGIN(directive); }
<INITIAL>@\{ { BEGIN(eval); return token::BEGIN_EVAL; }
<INITIAL>{EOL} {
yylloc->lines(1);
return token::EOL;
}
<INITIAL>{EOL} { return token::EOL; }
<INITIAL><<EOF>> { yyterminate(); }
<directive,expr,eval,end_line><<EOF>> { driver.error(*yylloc, "unexpected end of file"); }
......@@ -200,6 +193,16 @@ CONT \\\\{SPC}*
%%
void
TokenizerFlex::location_increment(Tokenizer::parser::location_type *yylloc, const char *yytext)
{
while (*yytext != 0)
if (*yytext++ == '\n')
yylloc->lines(1);
else
yylloc->columns(1);
}
/* This implementation of TokenizerFlexLexer::yylex() is required to fill the
* vtable of the class TokenizerFlexLexer. We define the scanner's main yylex
* function via YY_DECL to reside in the TokenizerFlex class instead. */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment