Flex - идентификаторы типа float / int / id - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь создать гибкий файл, который будет распознавать числа с плавающей запятой и целые числа и id: Valid int - нельзя начинать с 0. Valid float - его представление должно включать экспоненту, значение которой представляет собой целое число со знаком или без знака 2.78 е + 10. Действительный идентификатор - может начинаться только с буквы нижнего регистра, и несколько знаков подчеркивания не могут появляться один за другим

Я не уверен, где я ошибаюсь, если у меня есть только число с плавающей точкой, я получаю обратно с плавающей точкой также 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.

1 Ответ

0 голосов
/ 07 апреля 2020

У вас есть несколько проблем в вашем коде: (сверху вниз)

  • Sign - это плохо ... вы говорите, что знак является одним из +, | или -. Вы использовали три символа в квадратных скобках [ и ], что делает их возможными ... вы можете использовать (\+|-) или [+-], но не то, что вы написали. Чтобы - был принят не как индикатор диапазона, нужно прикрепить его к одной из квадратных скобок, которые разделяют кодировку (лучше до последней, поэтому, если вам нужно использовать символ отрицания ^, Вы можете сделать это без помех)
  • Трейлер экспоненты с плавающей точкой допускает как e, так и E, поэтому фактическое регулярное выражение должно быть [eE].
  • a Число с плавающей точкой может начинаться с 0. вы можете иметь что-то вроде -00013.26 и быть действительным ...
  • ваше число с плавающей запятой должно иметь цифры по обе стороны от точки ., так что вы не узнаете ничего подобного 3. или .26 как числа с плавающей запятой. Вы написали ([1-9]+(\.({DIGIT}+{Expo}{DIGIT}+))), который принимает переменное количество цифр в наборе [1-9] (вы запрещаете 0 перед десятичной запятой), но всегда больше нуля, с точкой и последующим хотя бы одним ди git после точки ... это делает 41.e-21 не распознанным как число с плавающей точкой. Даже 40.25 не будет распознаваться как число с плавающей запятой (но как токены 4 (целое число), за которыми следуют 0 целое число и точка (которая будет выводиться по умолчанию для вывода), а затем целое число 25)
  • вы не разрешаете ставить знаки перед числом (это часто встречается в реализации компилятора, но не для чтения числовых последовательностей, когда вы пытаетесь) Вы не включили поддержку знака перед числом ... это причина того, что 41.e-21 анализируется как Int (41), . (повторяется), e (идентификатор), - (здесь недопустимо в качестве знака, потому что вы не t разрешить целые числа со знаком) и 21 как целое число.
  • вы не можете принимать целые числа менее двух цифр: опять же, использование + заставляет вас иметь одну ди git ( отличается от 0), за которым следует по крайней мере еще один ди git ... это делает меня sh у вас на четвертой и пятой строках.

Так что единственное, что вы узнаете правильно это идентификатор, который, кстати, должен начинаться со строчной буквы алфавита c. .. Вы не включили поддержку начальных идентификаторов в верхнем регистре.

...