Difference between revisions of "The Flex Lexical Analyzer/Exercise 5 - Removing the actions from a Flex specification"

From Wiki**3

< The Flex Lexical Analyzer
(New page: == The Problem (in Portuguese) == Crie um analisador lexical (especificação para a ferramenta Flex) que aceite uma especificação Flex e que a copie para a saída sem as acções assoc...)
 
(The Solution)
Line 27: Line 27:
  
 
== The Solution ==
 
== The Solution ==
 +
 +
[EXPLANATION COMING SOON]
  
 
<text>
 
<text>

Revision as of 21:53, 11 April 2010

The Problem (in Portuguese)

Crie um analisador lexical (especificação para a ferramenta Flex) que aceite uma especificação Flex e que a copie para a saída sem as acções associadas às regras. Codifique todas as rotinas auxiliares.

Uma especificação Flex, está dividida em três zonas separadas por %% (declarações, regras, código). As zonas de declarações e código devem ser copiadas integralmente para a saída.

Considere que cada regra Flex começa com um padrão (possivelmente precedido por uma lista de condições entre < e >), seguido por espaços brancos ou tabulações e por uma acção. Cada acção (constituída por código C/C++ arbitrário) pode ser escrita ao longo de várias linhas se estiver delimitada por {}, caso contrário, termina no final da linha. Cada padrão é composto por símbolos do alfabeto da linguagem e por vários operadores. Espaços que apareçam nos padrões devem ser precedidos por \ ou aparecer entre aspas (").

Exemplo: <text> %option stack noyywrap yylineno 8bit debug %option c++ yyclass="CompactScanner" outfile="CompactScanner.cpp" %{

  1. include <string>
  2. include <cdk/nodes/Node.h>
  3. include "Scanner.h"
  4. include "Parser.tab.h"

%} %% " " return T_SPACE; [A-Za-z][A-Za-z0-9_]* {

                          yylval.s = new std::string(yytext);
                          return T_VARIABLE;
                      }

%% </text>

The Solution

[EXPLANATION COMING SOON]

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

  1. include <iostream>

inline void yyerror(const char *msg) {

 std::cerr << "Error at " << yylineno << ": " << msg << std::endl;

} %} %x X_RULES X_RANGE X_STRING X_CODE1 X_CODE2 X_STRIGN X_CHARIGN X_COMMENT %%

^"%%" ECHO; yy_push_state(X_RULES);

<X_RULES>^[ \t]+.*\n ECHO; //lines to be ignored

<X_RULES>"[" ECHO; yy_push_state(X_RANGE); <X_RANGE>"]" ECHO; yy_pop_state(); <X_RANGE>"\\[" ECHO; <X_RANGE>"\\]" ECHO; <X_RANGE>. ECHO; <X_RANGE>\n yyerror("newline in range");

<X_RULES>\\\" ECHO; //avoid erroneous transition <X_RULES>\" ECHO; yy_push_state(X_STRING); <X_STRING>\" ECHO; yy_pop_state(); <X_STRING>\\\" ECHO; <X_STRING>. ECHO; <X_STRING>\n yyerror("newline in string");

<X_RULES>[ \t]+ yy_push_state(X_CODE1); <X_CODE1>\n ECHO; yy_pop_state(); <X_CODE1>"{" yy_push_state(X_CODE2); <X_CODE2>"}" yy_pop_state();

<X_CODE1,X_CODE2>\' yy_push_state(X_CHARIGN); <X_CHARIGN>\' yy_pop_state(); <X_CHARIGN>\\\'  ; <X_CHARIGN>.  ; <X_CHARIGN>\n yyerror("newline in char");

<X_CODE1,X_CODE2>\" yy_push_state(X_STRIGN); <X_STRIGN>\\\"  ; <X_STRIGN>\" yy_pop_state(); <X_STRIGN>.  ; <X_STRIGN>\n yyerror("newline in string");

<X_RULES,X_CODE1,X_CODE2>"/*" yy_push_state(X_COMMENT); <X_COMMENT>"/*" yy_push_state(X_COMMENT); <X_COMMENT>"*/" yy_pop_state(); <X_COMMENT>.|\n  ;

<X_RULES,X_CODE1,X_CODE2>"//".*$  ; <X_CODE1>.  ; <X_CODE2>.|\n  ;

<X_RULES>^"%%" ECHO; yy_pop_state(); /* code section */

<INITIAL,X_RULES>.|\n ECHO; /* echo the rest */

%% int main() {

 return yylex();

} </text>