Hi team,
I am learning the yacc & lex and want to use it to make a config parser, as you can see, the config file is following these rules:
key = value
For example:
memory_limit = 512
memory_unit = 'MB'
time_limit = 12
time_unit = 's'
And I make such a yacc & lex rule file:
/*
config.y
The yacc rule file to analyse the config string
Wen Yi
*/
%{
#include <stdio.h>
int yylex();
int yyerror(char *s);
%}
%token NUMBER STRING
%token TOKEN
%token EQUAL
%token NEWLINE
%union
{
double number;
char *string;
char *token;
}
%%
Rule:
| TOKEN EQUAL NUMBER NEWLINE { printf("%s = %f\n", $1.token, $3.number); }
| TOKEN EQUAL STRING NEWLINE { printf("%s = %s\n", $1.token, $3.string); }
;
%%
int main(int argc, char *argv[])
{
yyparse();
}
int yyerror(char *s)
{
puts(s);
}
config.y
The yacc rule file to analyse the config string
Wen Yi
*/
%{
#include <stdio.h>
int yylex();
int yyerror(char *s);
%}
%token NUMBER STRING
%token TOKEN
%token EQUAL
%token NEWLINE
%union
{
double number;
char *string;
char *token;
}
%%
Rule:
| TOKEN EQUAL NUMBER NEWLINE { printf("%s = %f\n", $1.token, $3.number); }
| TOKEN EQUAL STRING NEWLINE { printf("%s = %s\n", $1.token, $3.string); }
;
%%
int main(int argc, char *argv[])
{
yyparse();
}
int yyerror(char *s)
{
puts(s);
}
/*
config.l
The lex rule file to parse the config string
Wen Yi
*/
/*
Rule
Setting = 'value' (string)
Setting = value (numbder)
*/
%option noyywrap
%option noinput
%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
%}
%%
/*
Number
*/
"+"[0-9]+ { yylval.number = atof(yytext); return NUMBER; }
[0-9]+ { yylval.number = atof(yytext); return NUMBER; }
-[0-9]+ { yylval.number = atof(yytext); return NUMBER; }
[0-9]+.[0-9]+ { yylval.number = atof(yytext); return NUMBER; }
-[0-9]+.[0-9]+ { yylval.number = atof(yytext); return NUMBER; }
/*
String
*/
'.+' {
size_t length = strlen(yytext);
yytext[length - 1] = '\0';
yytext[0] = '\0';
memmove(yytext, yytext + 1, length - 1);
yylval.string = strdup(yytext);
return STRING;
}
"''" {
yylval.string = strdup("");
return STRING;
}
/*
Common Token
*/
[a-zA-z0-9_]+ { yylval.string = strdup(yytext);return TOKEN; }
/*
Equal =
*/
"=" { return EQUAL; }
/*
New line
*/
\n { return NEWLINE; }
/*
Other things
*/
. { ; }
%%
config.l
The lex rule file to parse the config string
Wen Yi
*/
/*
Rule
Setting = 'value' (string)
Setting = value (numbder)
*/
%option noyywrap
%option noinput
%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
%}
%%
/*
Number
*/
"+"[0-9]+ { yylval.number = atof(yytext); return NUMBER; }
[0-9]+ { yylval.number = atof(yytext); return NUMBER; }
-[0-9]+ { yylval.number = atof(yytext); return NUMBER; }
[0-9]+.[0-9]+ { yylval.number = atof(yytext); return NUMBER; }
-[0-9]+.[0-9]+ { yylval.number = atof(yytext); return NUMBER; }
/*
String
*/
'.+' {
size_t length = strlen(yytext);
yytext[length - 1] = '\0';
yytext[0] = '\0';
memmove(yytext, yytext + 1, length - 1);
yylval.string = strdup(yytext);
return STRING;
}
"''" {
yylval.string = strdup("");
return STRING;
}
/*
Common Token
*/
[a-zA-z0-9_]+ { yylval.string = strdup(yytext);return TOKEN; }
/*
Equal =
*/
"=" { return EQUAL; }
/*
New line
*/
\n { return NEWLINE; }
/*
Other things
*/
. { ; }
%%
I think I have ignored the extra characters, but when I running it:
[beginnerc@bogon config]$ make config
lex config.l
yacc -d config.y
gcc lex.yy.c y.tab.c
[beginnerc@bogon config]$ ./a.out
memory_limit = 512
memory_limit = 512.000000
memroy_unit = 'MB'
syntax error
[beginnerc@bogon config]$ ./a.out
memory_unit = 'MB'
memory_unit = MB
memory_limit = 512
syntax error
[beginnerc@bogon config]$
lex config.l
yacc -d config.y
gcc lex.yy.c y.tab.c
[beginnerc@bogon config]$ ./a.out
memory_limit = 512
memory_limit = 512.000000
memroy_unit = 'MB'
syntax error
[beginnerc@bogon config]$ ./a.out
memory_unit = 'MB'
memory_unit = MB
memory_limit = 512
syntax error
[beginnerc@bogon config]$
Can someone give me some advice? I really don't know why the 'syntax error' message showed.
Thanks in advance!
Yours,
Wen Yi