ожидаемое выражение до токена '=' - PullRequest
2 голосов
/ 18 июня 2019

Я хочу сделать парсер, который будет распечатывать выражения по шагам их вычисления. И когда я компилирую свой код, я не могу решить эту проблему. Я всегда получаю ошибку

code.l:13:1: error: expected expression before '=' token
  yylval.name = strdup(yytext);
 ^
code.l:18:1: error: expected expression before '=' token
  yylval.name = strdup(yytext);

 ^

Я пробовал много разных вещей, которые я считал проблемой, но безуспешно.

code.l

%{
#include <stdio.h>
#include <string.h>
#include "Assignment.tab.h"
%}

%%

" " ;
"\t" ;
[a-zA-Z]+
        {
        yylval.name = strdup(yytext);
        return(ID);
        }
[0-9]+
        {
        yylval.name = strdup(yytext);
        return(NUM);
        }
[-+=()*/\n]
        {
        return yytext[0];
        }
.
        {
        yyerror("unknown character");
        }

%%

code.y

%{
#include<stdio.h>

int temp = 0;
%}

%start list

%union
        {
        char *name;
        }
%token <name> ID
%token <name> NUM
%type <name> list stat expr

%left '+' '-'
%left '*' '/'
%left UMINUS

%%

list:
        |
        list stat '\n'
        |
        list error '\n'
        {
        yyerrok;
        }
        ;
stat:
        expr
        {
        printf("stat:t = (%s)\n:stat",$1);
        }
        |
        ID '=' expr
        {
        printf("stat:(%s) = (%s):stat", $1, $3);
        }
        ;

expr:
        '(' expr ')'
        {
        $$ = $2;
        }
        |
        expr '*' expr
        {
        printf("t = (%s) * (%s)", $1, $3);
        $$ = "t";
        }
        |
        expr '/' expr
        {
        printf("t = (%s) / (%s)", $1, $3);
        $$ = "t";
        }
        |
        expr '+' expr
        {
        printf("t = (%s) + (%s)", $1, $3);
        $$ = "t";
        }
        |
        expr '-' expr
        {
        printf("t = (%s) - (%s)", $1, $3);
        $$ = "t";
        }
        |
        '-' expr %prec UMINUS
        {
        printf("t = -(%s)", $2);
        $$ = "t";
        }
        |
        ID
        {
        $$ = $1;
        }
        |
        NUM
        {
        $$ = $1;
        }
        ;

%%

main()
{
 return(yyparse());
}

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

yywrap()
{
  return(1);
}

Мне не нужно решение для моего конечного проекта, мне просто нужно найти причину ошибки. Любая идея полезна.

EDIT: Файл Assignment.tab.h


#ifndef YY_YY_ASSIGNMENT_TAB_H_INCLUDED
# define YY_YY_ASSIGNMENT_TAB_H_INCLUDED
/* Enabling traces.  */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
#if YYDEBUG
extern int yydebug;
#endif

/* Tokens.  */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
   /* Put the tokens into the symbol table, so that GDB and other debuggers
      know about them.  */
   enum yytokentype {
     ID = 258,
     NUM = 259,
     UMINUS = 260
   };
#endif


#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
/* Line 2058 of yacc.c  */
#line 10 "Assignment.y"

        char *name;


/* Line 2058 of yacc.c  */
#line 67 "Assignment.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif

extern YYSTYPE yylval;

#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
#else
int yyparse ();
#endif
#else /* ! YYPARSE_PARAM */
#if defined __STDC__ || defined __cplusplus
int yyparse (void);
#else
int yyparse ();
#endif
#endif /* ! YYPARSE_PARAM */

#endif /* !YY_YY_ASSIGNMENT_TAB_H_INCLUDED  */

Ответы [ 2 ]

6 голосов
/ 18 июня 2019

Действие в правиле lex должно начинаться с той же строки, что и шаблон. Так что вам нужно написать, например

[a-zA-Z]+  {
    yylval.name = strdup(yytext);
    return(ID);
    }

Что бы это ни стоило, это требование четко указано в разделе руководства flex о формате входного файла :

Раздел правил гибкого ввода содержит ряд правил вида:

pattern   action

где шаблон должен быть с отступом и действие должно начинаться с той же строки.

Это ограничение, насколько я знаю, присутствует во всех реализациях lex, хотя последствия отличаются. Я процитировал руководство по Flex, поскольку считаю его более читабельным, чем описание Posix, а также описывает множество полезных функций, предназначенных только для flex.

0 голосов
/ 18 июня 2019

Если вы посмотрите на сгенерированный файл lex.yy.c, вы в конечном итоге найдете код вроде:

case 4:
YY_RULE_SETUP
#line 13 "code.l"
= strdup(yytext);
        YY_BREAK

Это явно не то, что вы имели в виду. Как отметили Rici в их ответе , проблема заключается в том, что начало действия должно следовать на той же строке, что и шаблон.

[a-zA-Z]+   {
            yylval.name = strdup(yytext);
            return(ID);
            }

Flex также выдает предупреждение:

code.l:18: warning, rule cannot be matched
code.l:23: warning, rule cannot be matched

Вы бы неплохо исправили подобные предупреждения перед компиляцией сгенерированного кода C.

...