Print tokens properly using Lex and Yacc

倾然丶 夕夏残阳落幕 提交于 2019-12-13 05:32:48

问题


I'm having difficulties printing a sequence of tokens that behaves recursively. To better explain, I will show the sections of the corresponding codes: First, the code on Lex:

%{
    #include <stdio.h>
    #include "y.tab.h"

   installID(){
   }

%}

abreparentese           "("
fechaparentese          ")"
pontoevirgula           ";"
virgula                 ","
id                      {letra}(({letra}|{digito})|({letra}|{digito}|{underline}))*
digito                  [0-9]
letra                   [a-z|A-Z]
porreal                 "%real"
portexto                "%texto"
porinteiro              "%inteiro"
leia                    "leia"

%%

{abreparentese}     { return ABREPARENTESE; }
{fechaparentese}    { return FECHAPARENTESE; }
{pontoevirgula}     { return PONTOEVIRGULA; }
{virgula}           { return VIRGULA; }
{id}                { installID();
                      return ID; }
{porinteiro}        { return PORINTEIRO; }
{porreal}           { return PORREAL; }
{portexto}          { return PORTEXTO; }
{leia}              { return LEIA;}

%%

int yywrap() {
   return 1;
}

Now, the code on Yacc:

%{
   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   #include <stdbool.h>
   #define YYSTYPE char*
   int yylex(void);
   void yyerror(char *);
   extern FILE *yyin, *yyout;
   extern char* yytext;
%}

%token ABREPARENTESE FECHAPARENTESE PONTOEVIRGULA VIRGULA ID PORREAL PORTEXTO PORINTEIRO LEIA
%%
programs : programs program
      | program
      | ABREPARENTESE {fprintf(yyout,"%s",yytext);}
      | FECHAPARENTESE {fprintf(yyout,"%s",yytext);}
      ;

program:
     leia
;

leia: 
    LEIA ABREPARENTESE entradas ids FECHAPARENTESE PONTOEVIRGULA
  {
    fprintf(yyout,"scanf(\"%s\",%s);",$3,$4);
  }
;

 entradas:
      tipo_entrada VIRGULA entradas {fprintf(yyout,"%s,",$1);}
      | tipo_entrada VIRGULA {fprintf(yyout,"%s", $1); }
 ;

 tipo_entrada:   
            | PORREAL {$$ = "%f";}
            | PORTEXTO {$$ = "%c";}
            | PORINTEIRO {$$ = "%d";}
 ;

 ids:    
       id VIRGULA ids {fprintf(yyout,"&%s,",$1);} 
       | id {fprintf(yyout,"&%s",$1);}
 ;

 id:
    ID {$$ = strdup(yytext);}
 ;

 %%
 void yyerror(char *s) {
fprintf(stderr, "%s\n", s);
}

int main(int argc, char *argv[]){
   yyout = fopen(argv[2],"w");
   yyin = fopen(argv[1], "r");
   yyparse();
   return 0;
}

I believe I have copied all the relevant part of my problem on the code (some things maybe I forgot to copy and paste), however my problem is this part of the code:

leia: LEIA ABREPARENTESE entradas ids FECHAPARENTESE PONTOEVIRGULA
  {

    fprintf(yyout,"scanf(\"%s\",%s);",$3,$4);


  }
;

In the input file, I have the following line:

leia (%real, %inteiro, id1, id2);

The expectation was this on the output file:

scanf("%f,%d",&id1,&id2);

But actually this is the result in the output file:

%d%f,&id2&id1,scanf("%f",id1);

Can you help me solve this problem? How do I print the tokens in the right place?


回答1:


Normally, with bottom-up parsing, we use left-recursive productions, which has the result that the productions are reduced from left to right.

When you use right recursion, then productions are stacked up until the end, and then popped off the stack and therefore reductions are executed right-to-left.

So for example, it would be more usual to write:

 ids: id
    | ids ',' id

and then the semantic rules will execute in the expected order.



来源:https://stackoverflow.com/questions/35921723/print-tokens-properly-using-lex-and-yacc

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!