c – 在用户输入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;
}

请帮忙.

最佳答案 一种更清洁的解决方案是以预期的方式使用弹性扫描器,即连续地将词法标记返回给其调用者,每次调用一个标记.

这意味着您需要一些方法让扫描仪识别它遇到的令牌类型.通常,您将使用枚举(或更传统的#defines集合),这些枚举放在头文件中,扫描程序及其调用者都可以包含该头文件.如果您使用解析器生成器(如yacc或bison),则会自动为您生成此标头.

您还需要一些方法让扫描程序返回令牌的“语义值”.在这个简单的情况下,这是没有必要的,因为你不会对令牌的值做任何事情,除了立即打印出来.这使得可以使用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);

现在,我们还需要一些方法将这些枚举值与人类可读的描述相关联.简单的方法是以与值相同的顺序创建字符串表.在生产代码中,您可能希望选择更易于维护的内容.请记住,令牌代码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;
}

最后,有点清理的词法分析器:

文件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全局(或重入扫描器的参数)来保存位置信息,为该信息添加令牌计数.

点赞