The Flex Lexical Analyzer/Exercise 9 - Comments/code ratio in C++ and Java

From Wiki**3

< The Flex Lexical Analyzer
Revision as of 09:37, 7 April 2018 by Root (talk | contribs) (The Solution)

Test 1 201608081800.

The Problem (in Portuguese)

Crie um analisador lexical (especificação para a ferramenta Flex) que aceite um ficheiro C++ (ou Java) 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. Espaços brancos são contabilizados como código.

Note que nem todas as ocorrências das sequências de início e fim de comentário (i.e., //, /*, */), correspondem sempre a delimitadores de comentários. Considere ainda que os comentários em C++ (ou Java) não podem estar aninhados (a sequência /* 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

Comments in the specification explain the ideas.

<text> %option stack 8bit noyywrap yylineno %{

  1. include <iostream>

namespace {

 // module-private variables
 int code_length = 0;
 int comments_length = 0;

} void yyerror(const char *msg); %}

%x xCHAR xSTRING xCOMMENT %%

/* detect chars: they may contain double quotes that do not start strings */

\' code_length += yyleng; yy_push_state(xCHAR); <xCHAR>\' code_length += yyleng; yy_pop_state(); <xCHAR>\\\' code_length += yyleng; // escaped quote (not a true char delimiter) <xCHAR>\\\\ code_length += yyleng; // escaped backslash <xCHAR>. code_length += yyleng; // we are not controlling char length <xCHAR>\n yyerror("newline in char");

/* detect strings: they may contain false comment delimiters */

\" code_length += yyleng; yy_push_state(xSTRING); <xSTRING>\" code_length += yyleng; yy_pop_state(); <xSTRING>\\\" code_length += yyleng; // escaped double quote (not a true string delimiter) <xSTRING>\\\\ code_length += yyleng; // escaped backslash <xSTRING>. code_length += yyleng; <xSTRING>\n yyerror("newline in string");

"/*" comments_length += yyleng; yy_push_state(xCOMMENT); <xCOMMENT>"*/" comments_length += yyleng; yy_pop_state(); <xCOMMENT>.|\n comments_length += yyleng; // everything else (including other "/*" sequences)

"//".*$ comments_length += yyleng;

.|\n code_length += yyleng;

%% void yyerror(const char *msg) { std::cerr << msg << std::endl; } int main() {

 yylex();
 std::cout << "Code length: " << code_length << std::endl;
 std::cout << "Comments length: " << comments_length << std::endl;

} </text>