Difference between revisions of "The YACC Parser Generator/Exercise 7"

From Wiki**3

< The YACC Parser Generator
(Created page with "{{TOCright}} == Problema == Considere uma linguagem constituída por uma sequência de intervalos, possivelmente vazia. Os intervalos são definidos por valores reais (os li...")
 
(How to Compile?)
 
(4 intermediate revisions by the same user not shown)
Line 9: Line 9:
  
 
The lexical analyzer ('''minint.l''') is very simple and limited to recognizing the indispensable tokens.
 
The lexical analyzer ('''minint.l''') is very simple and limited to recognizing the indispensable tokens.
<text>
+
<source lang="text">
 
%option noyywrap
 
%option noyywrap
 
%{
 
%{
Line 26: Line 26:
  
 
%%
 
%%
</text>
+
</source>
  
 
== The Syntactic Analyzer (YACC) Specification ==
 
== The Syntactic Analyzer (YACC) Specification ==
  
 
The syntactic analyzer ('''minint.y''') will be built to immediately compute the maximum values in a syntax-directed fashion (as they occur). Note that the use of numeric limits is correct, but other such names would be acceptable (e.g. '''MAXDOUBLE''').
 
The syntactic analyzer ('''minint.y''') will be built to immediately compute the maximum values in a syntax-directed fashion (as they occur). Note that the use of numeric limits is correct, but other such names would be acceptable (e.g. '''MAXDOUBLE''').
<text>
+
<source lang="text">
 
%{
 
%{
 
#include <limits>
 
#include <limits>
 
#include <iostream>
 
#include <iostream>
 +
extern int yylex();
 
inline void yyerror(const char *msg) { std::cerr << msg << std::endl; }
 
inline void yyerror(const char *msg) { std::cerr << msg << std::endl; }
 
%}
 
%}
Line 57: Line 58:
  
 
%%
 
%%
extern int yylex();
 
 
extern int yyparse();
 
extern int yyparse();
 
int main() { return yyparse(); }
 
int main() { return yyparse(); }
</text>
+
</source>
  
 
== How to Compile? ==
 
== How to Compile? ==
Line 70: Line 70:
 
The YACC specification is processed as follows (files '''y.tab.h''', needed by the Flex-generated code, and '''y.tab.c'''):
 
The YACC specification is processed as follows (files '''y.tab.h''', needed by the Flex-generated code, and '''y.tab.c'''):
  
   byacc -dtv minint.y
+
   bison -dtv minint.y
  
 
Compiling the C/C++ code (it is C++ simply because we programmed the extra code in that language):
 
Compiling the C/C++ code (it is C++ simply because we programmed the extra code in that language):
  
   g++ -std=c++11 -c lex.yy.c
+
   g++ -std=c++17 -c lex.yy.c
   g++ -std=c++11 -c y.tab.c
+
   g++ -std=c++17 -c y.tab.c
 
   g++ -o minint y.tab.o lex.yy.o
 
   g++ -o minint y.tab.o lex.yy.o
  
 
[[category:Compiladores]]
 
[[category:Compiladores]]
 
[[category:Ensino]]
 
[[category:Ensino]]

Latest revision as of 16:35, 21 April 2021

Problema

Considere uma linguagem constituída por uma sequência de intervalos, possivelmente vazia. Os intervalos são definidos por valores reais (os limites inferior e superior são separados por :). Os intervalos são separados entre si por vírgulas (,). A representação dos números reais é como em C++. Pretende-se determinar a largura do menor intervalo da sequência, ignorando os intervalos inválidos (em que o limite superior é menor que o limite inferior).

Escreva uma especificação YACC para o problema acima. Codifique toda a especificação (incluindo as zonas de declarações e de regras) e todas as funções auxiliares. Não utilizar variáveis globais.

The Lexical Analyzer (Flex) Specification

The lexical analyzer (minint.l) is very simple and limited to recognizing the indispensable tokens.

%option noyywrap
%{
#include <string>
#include "y.tab.h"
%}
%%

[0-9]*\.[0-9]+([Ee][-+]?[0-9]+)?        yylval.d = std::stod(yytext); return tDOUBLE;
[0-9]+\.[0-9]*([Ee][-+]?[0-9]+)?        yylval.d = std::stod(yytext); return tDOUBLE;
[0-9]+([Ee][-+]?[0-9]+)                 yylval.d = std::stod(yytext); return tDOUBLE;

[,:]                                    return *yytext;

.|\n                                    ; /* ignore the rest */

%%

The Syntactic Analyzer (YACC) Specification

The syntactic analyzer (minint.y) will be built to immediately compute the maximum values in a syntax-directed fashion (as they occur). Note that the use of numeric limits is correct, but other such names would be acceptable (e.g. MAXDOUBLE).

%{
#include <limits>
#include <iostream>
extern int yylex();
inline void yyerror(const char *msg) { std::cerr << msg << std::endl; }
%}

%union { double d; }

%token <d> tDOUBLE
%type  <d> sequence interval

%%

top : sequence    { std::cout << "shortest interval: " << $1 << std::endl; }
    | /* empty */ { std::cout << "empty sequence"            << std::endl; }
    ;

sequence : interval              { $$ = $1; }
         | sequence ',' interval { $$ = std::min($1, $3); }
         ;

interval : tDOUBLE ':' tDOUBLE { $$ = $1 > $3 ? std::numeric_limits<double>::max() : $3 - $1; }
         ;

%%
extern int yyparse();
int main() { return yyparse(); }

How to Compile?

The Flex specification is processed as follows (the file lex.yy.c is produced):

 flex minint.l

The YACC specification is processed as follows (files y.tab.h, needed by the Flex-generated code, and y.tab.c):

 bison -dtv minint.y

Compiling the C/C++ code (it is C++ simply because we programmed the extra code in that language):

 g++ -std=c++17 -c lex.yy.c
 g++ -std=c++17 -c y.tab.c
 g++ -o minint y.tab.o lex.yy.o