1
votes

I have the following config file that I need to parse.

[ main ]
e_type=0x1B

The lex(test.l) and yacc(test.y) files are given below

test.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);
}

test.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
    {

    }
    ;
%%

I have an include lex.h file that is included in test.y

#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

endif

I compile the files as follows.

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

The binary test that I get is giving

> opened config file 
line: 1 column: 1 error: syntax error main
1
HEXANUMBER in your .l file needs to be surrounded by {}o11c
@o11c - why is that?liv2hak
@o11c - tried that still I get the same errorliv2hak
First you need to trace which token you're getting the syntax error at. Include yytext in your syntax error message.user207421
Note that identifiers beginning with an underscore and a capital letter are reserved for the implementation for any purpose; you should not create identifiers such as _LEX_H_ yourself. In general, and with only a slight overstatement, you should not create identifiers that start with an underscore. You may use system-defined identifiers that start with underscore, but should not try to create your own. You'll often get away with it anyway, but it's wise to avoid trouble.Jonathan Leffler

1 Answers

2
votes

Your problem is the rule:

attribute_pair
    : T_E_TYPE '=' number

Your lexer returns T_EQUAL but the grammar expects '=' and the two are not equal. It was easy for me to spot; when I run the program, I get the report:

> opened config file 

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

So it was remarkably easy to find the problem. The yacc I'm using is actually bison:

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

When I fixed that, the error changed:

> opened config file 

error: syntax error, unexpected T_NUMBER, expecting NUMBER

Fixing that involved changing:

%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

(Drop T_NUMBER from first line; change NUMBER to T_NUMBER in third line.) And also:

number
    : T_NUMBER

(Change NUMBER to T_NUMBER.)

With both those changes, you get a successful run (no output other than the open message, but no errors either).