The Flex Lexical Analyzer/Exercise 11 - PASCAL code-to-comments ratio
From Wiki**3
The Problem (in Portuguese)
Crie um analisador lexical (especificação para a ferramenta Flex) que aceite um ficheiro da linguagem Pascal e que apresente na saída (std::cout) o rácio entre as dimensões (número de caracteres) do código e dos comentários no texto do programa. Considere apenas os comentários delimitados pelas sequências (* e *). Espaços brancos fora dos comentários são contabilizados como código.
Note-se que nem todas as ocorrências das sequências de início de comentários correspondem sempre a delimitadores desses elementos, em particular, em cadeias de caracteres. As cadeias de caracteres são delimitadas por plicas (') (considere que não existem aninhamentos neste caso). Considere ainda que os comentários em Pascal não podem estar aninhados (i.e., (* pode ocorrer num comentário, mas isso não implica aninhamento).
Considere que os ficheiros a processar estão bem formados (ou seja, os ficheiros não têm erros de escrita).
The Solution
%option 8bit noyywrap yylineno stack
%{
#include <iostream>
namespace {
double code = 0, comments = 0;
}
inline void yyerror(const char *msg) {
std::cerr << "Error at " << yylineno << ": " << msg << std::endl;
}
%}
%x X_STRING X_COMMENT
%%
\' code+=yyleng; yy_push_state(X_STRING);
<X_STRING>\'\' code+=yyleng; // two ' count as a single one inside a string
<X_STRING>\' code+=yyleng; yy_pop_state();
<X_STRING>. code+=yyleng;
<X_STRING>\n yyerror("newline in string");
"(*" comments+=yyleng; yy_push_state(X_COMMENT);
<X_COMMENT>"*)" comments+=yyleng; yy_pop_state();
<X_COMMENT>.|\n comments+=yyleng;
.|\n code++;
%%
extern int yylex();
int main() {
yylex();
if (comments == 0) comments = 1; // prevent division by 0
std::cout << (code/comments) << std::endl;
}