c - Yacc 程序给出错误 :"syntax error"

标签 c bison yacc lex text-parsing

我需要解析以下配置文件。

[ main ]
e_type=0x1B

下面给出了 lex(test.l) 和 yacc(test.y) 文件

测试.l

%option noyywrap
%option yylineno
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "y.tab.h"

int yylinenu = 1;
int yycolno=1;

/**
 * Forward declerations
 **/
void Number ();
void HexaNumber ();
unsigned char getHexaLex (char c);
unsigned int strtol16 (char * str);


%}

%option nounput
%option noinput
%option case-insensitive

/*-----------------------------------------------------------------
   Some macros (standard regular expressions)
------------------------------------------------------------------*/

DIGIT       [0-9]
HEXALETTER  [a-fA-F]
HEXANUMBER  [0][x](({DIGIT}|{HEXALETTER})+)
NUM         {DIGIT}+
HEXA        ({DIGIT}|{HEXALETTER}|[*])
STR         \"[^\"]*\"
WSPACE      [ \t]*
NEWLINE     [\n\r]        

/*----------------------------------------------------------------
   The lexer rules
------------------------------------------------------------------*/
%%

e_type                   { yylval.str = yytext; return T_E_TYPE; }
main                     { yylval.str = yytext; return T_MAIN_SECTION;}
{HEXANUMBER}             { yylval.n = atoi(yytext);  HexaNumber(); return T_NUMBER; }
=                        { return T_EQUAL; }
"["                      { return T_OPEN_BRACKET; }
"]"                      { return T_CLOSE_BRACKET;}

[^\t\n\r]                { }
{WSPACE}                 { } /* whitespace: (do nothing) */
{NEWLINE}                {  
                            yylinenu++;
                            return T_EOL;
                         }

%%

void Number () {
    yylval.n = atol(yytext);
}

测试.y

%{
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "y.tab.h"
#include "lex.h"

#define E_PARSE_DEBUG
#ifdef E_PARSE_DEBUG
// Some yacc (bison) defines
#define YYDEBUG 1       // Generate debug code; needed for YYERROR_VERBOSE
#define YYERROR_VERBOSE // Give a more specific parse error message 
#endif

#define E_DEBUG_STRINGIFY(x) #x
#define E_DEBUG_TOSTRING(x) E_DEBUG_STRINGIFY(x)
#define E_DEBUG_AT (__FILE__ ":" E_DEBUG_TOSTRING(__LINE__))

extern  int yyparse (void);
extern int yylinenu;
extern int yycolno;
void yyerror(const char *str)
{
  fprintf(stderr,"line: %d column: %d error: %s %s \n",yylinenu,yycolno,str,yylval.str);
}

int yywrap()
{
  return 1;
}

int main()
{
  printf("> "); 

  // open a file handle to a particular file:
  FILE *myfile = fopen("tmp.conf", "r");
  // make sure it is valid:
  if (!myfile) {
      printf("I can't open tmp.conf \n");
      return -1;
  }else
  {
    printf("opened config file \n");
  }
  // set lex to read from it instead of defaulting to STDIN:
  yyin = myfile;

  yyparse();

  return 0;
}
int lineno = 0;
%}

/*------------------------------------------------------------------
  Yacc declarations
------------------------------------------------------------------ */

/* The structure for passing value between lexer and parser */
/* In the lexer we know it by the name 'yylval'*/
%union {
   char *str;
   unsigned int n;
   void * distr;
   void * command;
}

%token T_E_TYPE T_HOSTID_TYPE T_MAIN_SECTION T_EQUAL T_OPEN_BRACKET T_CLOSE_BRACKET T_EOL
%token <str> STRING
%token <n> T_NUMBER
%type <n> number


%%
config_file
    : /* empty */
    {

    }
    | config_file config_file_section
    {

    }
    ;

config_file_section
    : T_OPEN_BRACKET T_MAIN_SECTION T_CLOSE_BRACKET attribute_list
    {

    }
    ; 

attribute_list
    : /* empty */
    {

    }
    | attribute_list attribute_pair
    {

    }
    ;
attribute_pair
    : T_E_TYPE T_EQUAL number
    {

    }
    ;

number
    : T_NUMBER
    {

    }
    ;
%%

我有一个包含在 test.y 中的 include lex.h 文件

#ifndef _LEX_H_
#define _LEX_H_

#include <stdio.h>

#ifdef _LEX_CPP_
int lineno = 1; // line number count; this will be used for error messages later
#else
   // Import some variables
extern int lineno;
extern FILE *yyin;  // the input stream

// Function prototype
int yylex ();
#endif

结束

我按如下方式编译文件。

flex test.l
yacc -d  test.y
gcc lex.yy.c y.tab.c -Wall  -ll -o test -ldag

我得到的二进制test正在给出

> opened config file 
line: 1 column: 1 error: syntax error main

最佳答案

你的问题就是规则:

attribute_pair
    : T_E_TYPE '=' number

您的词法分析器返回 T_EQUAL 但语法需要 '=' 并且两者不相等。我很容易发现;当我运行该程序时,我收到报告:

> opened config file 

error: syntax error, unexpected T_EQUAL, expecting '='

所以发现问题非常容易。我使用的 yacc 实际上是 bison:

$ yacc --version
bison (GNU Bison) 2.3
…
$

当我解决这个问题时,错误发生了变化:

> opened config file 

error: syntax error, unexpected T_NUMBER, expecting NUMBER

修复涉及更改:

%token T_E_TYPE T_HOSTID_TYPE T_MAIN_SECTION T_EQUAL T_OPEN_BRACKET T_CLOSE_BRACKET
%token <str> STRING
%token <n> T_NUMBER

(从第一行删除 T_NUMBER;将第三行的 NUMBER 更改为 T_NUMBER。)此外:

number
    : T_NUMBER

(将 NUMBER 更改为 T_NUMBER。)

完成这两项更改后,您将成功运行(除了打开消息之外没有任何输出,但也没有错误)。

关于c - Yacc 程序给出错误 :"syntax error",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31799424/

相关文章:

c++ - 柔性和 Bison :C++ class

Bison/Flex 解析器获取字符串作为标记值

python - PLY : Parsing error. 规则意外匹配空标记集

_Atomic 类型说明符和限定符之间的 C11 语法歧义

c - 带有Linux的C中套接字的奇怪段错误

c++ - Yacc 中 ';' token 之前的预期类型说明符

c - 询问 msgrcv ,不适用于根据优先级接受消息

c++ - Bison :轮类减少冲突

c - 我在函数定义中犯了什么错误(C)

python - 从 c 字符串创建可用的 python 函数(sympy 用例)