用户在 flex 中输入后显示消息

Display message after user input in flex

我有以下用 flex 编写的代码片段。我需要显示此消息:

{printf("\n%-20s%-30s%-10s\n", "Lexeme", "Unite lexicale", "Indice");}

用户输入后的第一件事,我试图找到解决方案,但似乎没有任何效果。

%{
int i=1;
%}
lettre [a-zA-Z]+
nombre_entier (\+|\-)?[0-9]+
nombre_reel (\+|\-)?[0-9]+\.[0-9]+((e|E)(\-|\+)?[0-9]+)?
id {lettre}({lettre}|[0-9])*
%%
$              { exit(0);}
[ \t]+          {/*ignorer*/}
\n              {i=1;}
ENTIER|REEL     {printf("%-20s%-30s%-10d\n",yytext, "Mot_cle", i++);
                 printf("-----------------------------------------------------\n");}
{id}            {printf("%-20s%-30s%-10d\n",yytext, "ID", i++);
                 printf("------------------------------------------------------\n");}
{nombre_entier} {printf("%-20s%-30s%-10d\n",yytext, "nombre entier", i++);
                 printf("------------------------------------------------------\n");}
{nombre_reel}   {printf("%-20s%-30s%-10d\n",yytext, "nombre reel", i++);
                 printf("------------------------------------------------------\n");}
\(              {printf("%-20s%-30s%-10d\n",yytext, "parenthese ouvrante", i++);
                 printf("------------------------------------------------------\n");}
")"             {printf("%-20s%-30s%-10d\n",yytext, "parenthese fermante", i++);
                 printf("------------------------------------------------------\n");}
"+"|"-"|"*"|"/" {printf("%-20s%-30s%-10d\n",yytext, "operateur arithmetique", i++);
                 printf("------------------------------------------------------\n");}
"="             {printf("%-20s%-30s%-10d\n",yytext, "operateur d'affectation", i++);
                 printf("------------------------------------------------------\n");}
","             {printf("%-20s%-30s%-10d\n",yytext, "Virgule", i++);
                 printf("------------------------------------------------------\n");}
";"             {printf("%-20s%-30s%-10d\n",yytext, "Point virgule", i++);
                 printf("------------------------------------------------------\n");}
.               {printf("%-20s%-30s%-10d\n",yytext, "caractere inconnu", i++);
                 printf("------------------------------------------------------\n");}
%%
int main(){
    printf("Entrez le texte a analyser : \n");
    yylex();
    return 0;
}
int yywrap(){
    return 1;
}

请帮忙。

谢谢@DYZ 这就是我最后做的事情

%{
int i=1,j=0;
#define YY_INPUT(buf,result,max_size) \
    { \
    int c = getchar(); \
    result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \
    if(j++ == 0) \
        { \
        printf("\n%-20s%-30s%-10s\n", "Lexeme", "Unite lexicale", "Indice"); \
        printf("-----------------------------------------------------\n"); \
        } \
    }
%}

一个更简洁的解决方案是以预期的方式使用 flex 扫描器,即连续 return 词汇标记给它的调用者,每次调用一个标记。

这意味着您需要一些方法让扫描器识别它遇到的令牌类型。通常,您将使用一个枚举(或者,更传统地说,collection of #defines),它们被放置在一个 header 文件中,扫描器及其调用者都可以包含该文件.如果您使用 yacc 或 bison 等解析器生成器,此 header 将自动为您生成。

您还需要某种方式让扫描器 return 令牌的“语义值”。在这个简单的例子中,这是没有必要的,因为除了立即打印出来之外,您没有对令牌的值进行任何操作。这使得使用 yytext 全局变量成为可能(如果您的扫描器使用全局变量),但是在 flex 操作之外使用 yytext 是一个等待发生的错误,因为 yytext 和它指向的缓冲区是扫描仪内部状态的一部分,内容可以并且将会在没有警告的情况下发生变化。你可以在这里解决它,因为在下一次调用 yylex.

之前什么都不会改变

实际上,它可能看起来像这样:

文件:tokens.h

enum Token {
  T_FIN = 0,
  T_MOTCLE,
  T_ID,
  T_ENTIER,
  T_REEL,
  T_OUVRANTE,
  T_FERMANTE,
  T_OPERATEUR,
  T_AFFECT,
  T_VIRGULE,
  T_POINT_VIRGULE,
  T_INCONNU
};

const char* decrire(int jeton);

现在,我们还需要一些方法将这些枚举值与 human-readable 描述相关联。简单的方法是按与值相同的顺序制作一个 table 字符串。在生产代码中,您可能希望选择更易于维护的代码。记住token code 0习惯上用来表示输入结束,所以需要留出空间。

文件:tokens.c

#include <stdio.h>
#include "tokens.h"

static const char* descriptions = {
  "Fin d'entree",
  "Mot_cle",
  "ID",
  "Nombre entier",
  "Nombre reel",
  "Parenthese ouvrante",
  "Parenthese fermante"
  "Operateur arithmetique",
  "Operateur d'affectation",
  "Virgule",
  "Point virgule",
  "Caractere inconnu"
};

const char* decrire(int jeton) {
  if (jeton >= 0 && jeton <= T_INCONNU)
    return descriptions[jeton];
  else
    return "???";  /* This indicates a bug somewhere */
}

现在我们可以为这个词法分析器编写一个非常简单的应用程序,它打印出令牌流:

int main() {
  puts("Entrez le texte a analyser : ");
  int jeton = yylex();
  printf("\n%-20s%-30s%-10s\n", "Lexeme", "Unite lexicale", "Indice");
  puts("-----------------------------------------------------");
  for (int i = 1; jeton; jeton = yylex();) {
    printf("%-20s%-30s%-10d\n", yytext, decrire(jeton), token_count++);
    puts("------------------------------------------------------");
  }
  return 0;
}

最后,有点 cleaned-up 词法分析器:

文件tokens.l

%{
  #include "tokens.h"
  int token_count;
%}

%options noinput nounput noyywrap nodefault

%%
"$"                     { return T_FIN; }
[ \t]+                  { /*ignorer*/ }
\n                      { token_count = 1; }
ENTIER|REEL             { return T_MOTCLE; }
[[:alpha:]][[:alnum:]]* { return T_ID; }
[+-]?[[:digit:]]*       { return T_ENTIER; }
[+-]?[[:digit:]]+\.[[:digit:]]+([eE][+-]?[[:digit:]]*)? {
                          return T_REEL; }
"("                     { return T_OUVRANTE; }
")"                     { return T_FERMANTE; }
[-+*/]                  { return T_OPERATEUR; }
"="                     { return T_AFFECT; }
","                     { return T_VIRGULE; }
";"                     { return T_POINT_VIRGULE; }
.                       { return T_INCONNU; }

令牌计数的处理(以及行计数的缺失)不太理想;理想的解决方案是使用标准 yylloc 全局(或可重入扫描器的参数)来保存位置信息,并向该信息添加令牌计数。