【问题标题】:Flex - identfiy float/ int/ id tokensFlex - 识别 float/int/id 令牌
【发布时间】:2020-07-18 09:37:38
【问题描述】:

我正在尝试创建一个可以识别浮点数/整数和 id 的 flex 文件: 有效的 int - 不允许以 0 开头。 有效的浮点数表示必须包含指数,其值为带或不带符号 2.78e+10 的整数。 有效id-只能以小写字母开头,多个下划线不能一个接一个出现

我不确定我错在哪里,如果我只有浮点数,我会返回浮点数和 int 和 id,但是当所有内容组合在一个文件中时,它就不起作用了。

这是我创建的文件:

%option noyywrap


%{
#include "Token.h"
#include <stdio.h>
#include <stdlib.h>

static int skip_single_line_comment(int num); //function for one line comment 
static int skip_multiple_line_comment(int num);//function for multiple lines of comments

int line_num=0;

%}

ALPHA       ([a-zA-Z])
DIGIT       ([0-9])
Sign        ([+|-])
Expo        ([e]{Sign}?)
float_num   ([1-9]+(\.({DIGIT}+{Expo}{DIGIT}+)))
int_num     [1-9]{DIGIT}+
id      ([a-z]+({ALPHA}|{DIGIT}|(\_({ALPHA}|{DIGIT})))*)
%%


{float_num} {
         create_and_store_token(TOKEN_FLOAT, yytext, line_num); 
             fprintf(yyout,"Line %d : found token of type TOKEN_FLOAT, lexeme %s.\n", line_num, yytext);
        }

\n      {line_num++;}

{int_num}   {
         create_and_store_token(TOKEN_INTEGER,  yytext, line_num); 
                 fprintf(yyout,"Line %d : found token of type TOKEN_INTEGER , lexeme %s.\n", line_num, yytext);
                }

{id}        {
         create_and_store_token(TOKEN_ID, yytext, line_num); 
             fprintf(yyout,"Line %d : found token of type TOKEN_ID, lexeme %s.\n", line_num, yytext);
        }

"//"              {line_num=skip_single_line_comment(line_num); fprintf(yyout,"The number of the line is:%d.\n", line_num);}


"/*"             {line_num=skip_multiple_line_comment(line_num); fprintf(yyout,"The number of the line is:%d.\n", line_num);}



%%

static int
skip_single_line_comment(int num)
{
  char c;

  /* Read until we find \n or EOF */
  while((c = input()) != '\n' && c != EOF)
    ;

  /* Maybe you want to place back EOF? */
  if(c == EOF)
    unput(c);


    return num=num+1;
}


static int
skip_multiple_line_comment(int num)
{
  char c;

  for(;;)
  {
    switch(input())
    {
      /* We expect ending the comment first before EOF */
      case EOF:
        fprintf(stderr, "Error unclosed comment, expect */\n");
        exit(-1);
        goto done;
      break;
      /* Is it the end of comment? */
      case '*':
        if((c = input()) == '/'){
    num=num+1;
    goto done;
    }
        unput(c);
        break;
      default:
        /* skip this character */
        break;
    }
  }

done:
  /* exit entry */
  return num ;
}


void main(int argc, char **argv){ 

yyin=fopen("C:\\temp\\test1.txt","r");
yyout=fopen("C:\\temp\\test1Soltion.txt","w");

yylex();}

输入文件:

21
41.e-21
a_23_e4_5
8
1.1E+21
a1_c23_e4_56

输出:

Line 0 : found token of type TOKEN_INTEGER , lexeme 21.
Line 1 : found token of type TOKEN_INTEGER , lexeme 41.
.Line 1 : found token of type TOKEN_ID, lexeme e.
-Line 1 : found token of type TOKEN_INTEGER , lexeme 21.
Line 2 : found token of type TOKEN_ID, lexeme a_23_e4_5.
81.1E+Line 4 : found token of type TOKEN_INTEGER , lexeme 21.
Line 5 : found token of type TOKEN_ID, lexeme a1_c23_e4_56.

【问题讨论】:

  • 你的浮点数和整数的 RE 都是相似的,没有任何区别。这就是为什么它首先选择 int 而不是浮动,即使你认为它应该。请参阅example 词法分析器了解 C 语法。你会发现他们已经区分得很清楚了。

标签: c compilation flex-lexer


【解决方案1】:

你的代码有几个问题:(从上到下)

  • Sign 不好...您是说标志是 +|- 之一。您在方括号[] 之间使用了三个字符,这使得它们成为可能……您可以使用(\+|-)[+-],但不是您所写的。为了使 - 不被接受为范围指示符,请将其粘贴到分隔字符集的方括号之一(最好是最后一个,所以如果您必须使用否定 ^ 字符,您可以不受干扰地做到这一点)
  • 到浮点的指数尾部允许eE,因此实际的正则表达式应该是[eE]
  • 浮点数可以以0 开头。你可以有类似-00013.26 的东西并且是有效的......
  • 您的浮点数被强制在点. 的两边都有数字,因此您不会将3..26 之类的东西识别为浮点数。您编写了([1-9]+(\.({DIGIT}+{Expo}{DIGIT}+))),它接受集合[1-9] 中可变数量的数字(您不允许0 在小数点前面)但始终大于零,后跟​​一个点,并且后跟至少一个数字在点之后......这使得41.e-21 不被识别为浮点数。即使40.25 也不会被识别为浮点数(而是标记为4(整数),后跟0 整数和一个点(默认情况下将回显到输出),然后是整数25
  • 您不允许在数字前面放置符号(这在编译器实现中很常见,但在您尝试时不要读取数字序列)您没有包含对数字前面的符号的支持...这就是 41.e-21 被解析为 Int(41), .(echoed), e(identifier),- 的原因(在这里无效,因为您不允许签名整数),21 为整数。
  • 你不接受小于两位数的整数:同样,+ 的使用让你有一个数字(不同于0)后跟至少一个数字......这使得网格你有第四和第五行。

所以你唯一能正确识别的是标识符,顺便说一下,它必须以小写字母开头......你还没有包含对大写开头标识符的支持。

【讨论】:

  • 如果您认为此答案解决了您的问题,请将其标记为已选答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-29
  • 2016-11-25
  • 1970-01-01
相关资源
最近更新 更多