The YACC Parser Generator/Exercise 4: Difference between revisions

From Wiki**3

< The YACC Parser Generator
 
Line 1: Line 1:
== Problema ==
#REDIRECT [[ist:The YACC Parser Generator/Exercise 4]]
Pretende-se fazer uma calculadora de expressões lógicas usando a interpretação dirigida pela sintaxe. A calculadora utiliza 10 variáveis designadas pelos números 0 a 9 da variável ival associada ao token '''VAR'''. Os literais verdadeiro e falso são designados pelos tokens '''VERD''' e '''FALS''', respectivamente. O cálculo é efectuado através de uma sequência de expressões terminadas por ';' ou ',' consoante o resultado da expressão deva ser impresso ou não, respectivamente. A atribuição de uma expressão a uma variável é efectuada pelo operador '=', não associativo. As expressões utilizam os seguintes operadores, por ordem decrescente de prioridade:
 
* '''negação lógica:''' operador unário pré-fixado, não associativo, designado por '!'.
* '''E lógico:''' operador binário, associativo à esquerda, designado por '&'.
* '''OU inclusivo lógico:''' operador binário, associativo à esquerda, designado por '|'.
* '''OU exclusivo lógico:''' operador binário, associativo à direita, designado por ' ~ '.
* '''comparação:''' operadores binários, '==', e '!=', associativos à esquerda, designados por '''EQ''' e '''NE'''.
 
A prioridade dos operadores pode ser alterada utilizando parenteses curvos '(' e ')'. No início todos os registos têm o valor lógico falso.
 
Todas as rotinas auxiliares devem ser codificadas.
 
== The Lexical Analyzer (Flex) Specification ==
 
The lexical analyzer (<tt>vars.l</tt>) is very simple and limited to recognizing variable names (token '''tVAR'''), integers numbers (token '''tVAL'''), and the operators themselves.
<text>
%option noyywrap
%{
#include <cstdlib>
#include "y.tab.h"
%}
%%
[[:digit:]]    yylval.i = strtol(yytext, NULL, 10); return tVAR;
"VERD"          yylval.i = !0;                      return tVAL;
"FALS"          yylval.i =  0;                      return tVAL;
[!&|~<>()=]                                          return *yytext;
"=="                                                return tEQ;
"!="                                                return tNE;
.|\n            ; /* ignore all the rest */
%%
</text>
 
== The Syntactic Analyzer (YACC) Specification ==
 
The syntactic analyzer will be built to immediately compute the expressions in a syntax-directed fashion as they occur. It is, thus, important to use trees that build nodes as the expressions occur (left-recursive grammars). If the grammar were right-recursive, the last node would be the first to be built and the (syntax-directed) evaluation would be from the last expression to the first.
<text>
%{
#include <iostream>
#include <string>
#include <map>
namespace { int vars[10]; }
%}
 
%union { int i; }
 
%token tEQ tNE
%token<i> tVAR tVAL
%type<i> expr lval
 
%right '='
%left tEQ tNE
%right '~'
%left '|'
%left '&'
%nonassoc '!'
 
%%
list: stmt
    | list stmt
    ;
 
stmt: expr ','
    | expr ';'          { std::cout << ($1 ? "true" : "false") << std::endl; }
    ;
 
expr: tVAL              { $$ = $1; }
    | lval              { $$ = vars[$1]; }
    | lval '=' expr    { $$ = vars[$1] = $3; }
    | expr '~' expr    { $$ = $1 != $3; }
    | expr '|' expr    { $$ = $1 |  $3; }
    | expr '&' expr    { $$ = $1 &  $3; }
    | expr tEQ expr    { $$ = $1 == $3; }
    | expr tNE expr    { $$ = $1 != $3; }
    | '!' expr          { $$ = !$2; }
    | '(' expr ')'      { $$ =  $2; }
    ;
 
lval : tVAR { $$ = $1; }
    ;
 
%%
extern int yylex();
extern int yyparse();
void yyerror(char *s) { std::cout << s << std::endl; }
int main() { yyparse(); }
</text>
 
== How to Compile? ==
 
The Flex specification is processed as follows (the file <tt>lex.yy.c</tt> is produced):
 
  flex vars.l
 
The YACC specification is processed as follows (files <tt>y.tab.h</tt>, needed by the Flex-generated code, and <tt>y.tab.c</tt>):
 
  yacc -dtv vars.y
 
Compiling the C/C++ code (it is C++ simply because we programmed the extra code in that language):
 
  g++ -c lex.yy.c
  g++ -c y.tab.c
  g++ -o vars y.tab.o lex.yy.o
[[category:Compiladores]]
[[category:Ensino]]

Latest revision as of 23:42, 5 December 2018