Lex/Yacc failed to compile - yacc

I'm trying to create a compiler using Flex Windows (lex and yacc) for my school assignment, and I've successfully generated the .l and .y files. However, when trying to build the parser using Lex+Yacc build, I've encountered this error:
y.tab.h:48:4: error: expected ';', identifier or '(' before 'enum'
I've seen a similar problem in the following website:
https://bytes.com/topic/c/answers/861576-error-expected-identifier-before-token
But the place of occurrence for the error is different. Any suggestions about how I can solve this? Thanks in advance!
For reference, here is an excerpt from my y.tab.h file :
...
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype { //place of error
NEWLINE = 258,
VAR = 259,
INC = 260,
DEC = 261,
GTR = 262,
LSR = 263,
EQL = 264,
NEQ = 265,
LAND = 266,
LOR = 267,
NOT = 268,
INT = 269,
FLOAT = 270,
BOOL = 271,
STRING = 272,
PRINTLN = 273,
PRINT = 274,
TRUE = 275,
FALSE = 276,
IF = 277,
FOR = 278,
IFX = 279,
ELSE = 280,
END = 281,
GEQ = 282,
LEQ = 283,
REM_ASSIGN = 284,
QUO_ASSIGN = 285,
MUL_ASSIGN = 286,
SUB_ASSIGN = 287,
ADD_ASSIGN = 288,
INT_LIT = 289,
FLOAT_LIT = 290,
IDENT = 291,
STRING_LIT = 292
};
...
And these are my .l and .y files:
***Compiler_B24051260_HW2.l***
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "common.h"
#include "y.tab.h" /* header file generated by bison */
extern YYSTYPE yylval;
#define YY_NO_UNPUT
#define YY_NO_INPUT
%}
letter [a-zA-Z_]
digit [0-9]
id {letter}+({letter}|{digit})*
inumber {digit}+
fnumber {digit}*\.{digit}+
ws [ \t]+
quota [\"]
newline \n
misc [^a-zA-Z0-9]-\n
symbols [\%\^\#\&\!\#\*]
line_over [\./]
%x STR
%x CMT
%option yylineno
%%
"var" { return VAR; }
"int32" { return INT; }
"float32" { return FLOAT; }
"bool" { return BOOL; }
"true" { return TRUE;}
"false" { return FALSE;}
"println" { return PRINTLN; }
"print" { return PRINT; }
"if" { return IF; }
"else" { return ELSE; }
"for" { return FOR; }
"string" { return STRING; }
"\"" { BEGIN(STR);
return '"';
}
<STR>"\"" { BEGIN(INITIAL);
return '"';
}
<STR>[^\"]* { //yylval.usage->kind = kind_char;
//yylval.usage->usage.use_char = strdup(yytext);
yylval.s_val = strdup(yytext);
return STRING_LIT;
}
"/*" { BEGIN(CMT); }
<CMT>"*/" { BEGIN(INITIAL); }
<CMT>\n {;}
<CMT>. {;}
"//".* {;}
"+" { return '+'; }
"-" { return '-'; }
"*" { return '*'; }
"/" { return '/'; }
"%" { return '%'; }
"++" { return INC; }
"--" { return DEC; }
">" { return '>'; }
"<" { return '<'; }
">=" { return GEQ; }
"<=" { return LEQ; }
"==" { return EQL; }
"!=" { return NEQ; }
"=" { return '='; }
"+=" { return ADD_ASSIGN; }
"-=" { return SUB_ASSIGN; }
"*=" { return MUL_ASSIGN; }
"/=" { return QUO_ASSIGN; }
"%=" { return REM_ASSIGN; }
"&&" { return LAND ; }
"||" { return LOR; }
"!" { return NOT; }
"(" { return '('; }
")" { return ')'; }
"[" { return '['; }
"]" { return ']'; }
"{" { return '{';}
"}" { return '}';}
";" { return ';'; }
"," { return ','; }
\n { return NEWLINE; yylineno++;}
[ \t]+ {;}
{id} { //yylval.usage->kind = kind_char;
//yylval.usage->usage.use_char = strdup(yytext);
yylval.s_val = strdup(yytext);
printf ("current token:%s", yytext);
return IDENT;
}
{inumber} { //yylval.usage->kind = kind_int;
//yylval.usage->usage.use_in = atoi(yytext);
yylval.i_val = atoi(yytext);
return INT_LIT;
}
{fnumber} { //printf ("%.6f", yytext);
//yylval.usage->kind = kind_float;
//yylval.usage->usage.use_fl = atof(yytext);
yylval.f_val = atof(yytext);
return FLOAT_LIT;
}
{ws} {;}
<<EOF>> { static int once = 0;
if (once++) {
yyterminate();
}
yylineno++;
//return END;
}
. {;}
%%
int yywrap(void)
{
return 1;
}
Compiler_B24051260_HW2.y
%{
#include "common.h" //Extern variables that communicate with lex
#include <string.h>
//#include <ctype.h>
//#include <math.h>
//#define YYDEBUG 1
//int yydebug = 1;
//#define YYSTYPE struct NonTer
//#define YYSTYPE char *
extern int yylineno;
extern int yychar;
extern int yylex();
extern FILE *yyin;
struct {
enum { is_int, is_float, is_char, nothing } type;
union {
int ival;
float fval;
char *cval;
} val;
} my_array[52][7];
//struct
//int symbols[52][7];
//int symbolVal (char ID);
//void Update (char ID, int num);
int scope=0;
int id_index=0;
int arr_index=0;
int id_type=0;
int addr=0;
int ele_type=0;
void yyerror (char const *s)
{
printf("error: in line %d with token %d: %s\n", yylineno, yychar, s);
}
static void create_symbol();
static void insert_symbol(char *val ,int scope, int id_index, int data_type, int address, int line, int ele_type);
static int lookup_symbol(char *val);
static void dump_symbol();
%}
%error-verbose
%union
{
//int i_val;
//float f_val;
//char *s_val;
//struct NonTer* usage;
}
%token NEWLINE
%token VAR
%token INC DEC GTR LSR EQL NEQ
%token LAND LOR NOT
%token INT FLOAT BOOL STRING
%token PRINTLN PRINT
%token TRUE FALSE
%token IF FOR
%nonassoc IFX
%nonassoc ELSE
//%token INT_LIT /*FLOAT_LIT*/IDENT STRING_LIT
%token END
%left '<' '>' '=' LEQ GEQ
%left '+' '-'
%left '*' '/' '%'
%left ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN QUO_ASSIGN REM_ASSIGN
%union {
int i_val;
float f_val;
char *s_val;
}
/*%token <nval> INT_LIT
%token <nval> FLOAT_LIT
%token <nval> IDENT STRING_LIT*/
/*%token <usage> INT_LIT
%token <usage> FLOAT_LIT
%token <usage> IDENT STRING_LIT*/
%token <i_val> INT_LIT
%token <f_val> FLOAT_LIT
%token <s_val> IDENT STRING_LIT
//%token <f_val> FLOAT_LIT
%start Program
%%
Program
: StatementList END{;}
;
StatementList
: Statement StatementList {;}
| Statement {;}
;
Statement
: Exprs {;}
;
Exprs
: Expr NEWLINE Exprs
| Expr
Expr
: Arith {;}
| Declares {;}
| Change {;}
| Print {;}
| Logic {;}
| Assign {;}
| NEWLINE {;}
;
Print
: PRINTLN '(' IDENT ')' { printf ("PRINTLN id\n"); }
| PRINTLN '(' INT_LIT ')' { printf ("PRINTLN int\n"); }
| PRINTLN '(' FLOAT_LIT ')' {; }
| PRINTLN '(' Logic ')'{ printf ("PRINTLN bool\n");; }
| PRINTLN '(' Arith ')'{;}
;
Logic
: LateLogic LOR LateLogic { printf ("LOR\n");}
| LateLogic {;}
;
LateLogic
: LateLogic LAND LateLogic {printf ("LAND\n");}
| Compare {;}
| Is_not {;}
;
Compare
: Arith '>' Arith {printf ("GTR\n");}
| Arith '<' Arith {printf ("LSR\n");}
| Arith EQL Arith {printf ("EQL\n");}
| Arith NEQ Arith {printf ("NEQ\n");}
| Arith GEQ Arith {printf ("GEQ\n");}
| Arith LEQ Arith {printf ("LEQ\n");}
;
Is_not
: NOT TRUE {printf ("TRUE\n");
printf ("NOT\n");}
| NOT FALSE {printf ("FALSE\n");
printf ("NOT\n");}
| NOT Is_not {printf ("NOT\n");}
Arith
: Arith '+' Term {printf ("ADD\n");}
| Arith '-' Term {printf ("SUB\n");}
| Term
;
Term
: Factor
| Term '*' Factor {printf ("MUL\n");}
| Term '/' Factor {printf ("QUO\n");}
| Term '%' Factor {printf ("REM\n");;}
;
Factor
: '(' Arith ')' {;}
| IDENT { int e = lookup_symbol($1);
printf ("IDENT (name=%s, address=%d)\n" ,$1, e);}
| INT_LIT { printf ("INT_LIT %d\n", $1);}
| '+' INT_LIT {printf ("INT_LIT %d\n", $2);
printf ("POS\n");}
| '-' INT_LIT {printf ("INT_LIT %d\n", $2);
printf ("NEG\n");}
| FLOAT_LIT {printf ("FLOAT_LIT %.6f\n", $1);}
| '+' FLOAT_LIT {printf ("FLOAT_LIT %.6f\n", $2);
printf ("POS\n");}
| '-' FLOAT_LIT {printf ("FLOAT_LIT %.6f\n", $2);
printf ("NEG\n");}
;
Declares
: VAR IDENT INT NEWLINE{
//char a = $2.use_char;
printf("> Insert {%s} into symbol table (scope level: %d)\n", $2, scope);
id_type = 1;
ele_type=0;
insert_symbol($2,scope,id_index, id_type, addr, yylineno, ele_type);
addr = addr+1;
id_index++;
arr_index++;
//printf ("next address %d at array line %d", addr, id_index);
}
| VAR IDENT FLOAT NEWLINE{
printf("> Insert {%s} into symbol table (scope level: %d)\n", $2, scope);
id_type = 2;
ele_type=0;
insert_symbol($2,scope,id_index, id_type, addr, yylineno, ele_type);
addr++;
id_index++;
arr_index++;
//printf ("next address %d at array line %d", addr, id_index);
}
| VAR IDENT INT '=' INT_LIT NEWLINE {
printf ("INT_LIT %d\n", $5);
printf("> Insert {%s} into symbol table (scope level: %d)\n", $2, scope);
id_type = 1;
ele_type=0;
insert_symbol($2,scope,id_index,id_type, addr, yylineno, ele_type);
addr++;
id_index++;
arr_index++;
//printf ("next address %d at array line %d", addr, id_index);
}
| VAR IDENT FLOAT '=' FLOAT_LIT NEWLINE {
printf ("FLOAT_LIT %.5d\n", $5);
printf("> Insert {%s} into symbol table (scope level: %d)\n", $2, scope);
id_type = 2;
ele_type=0; // has nothing
insert_symbol($2,scope,id_index,id_type, addr, yylineno, ele_type);
addr++;
id_index++;
arr_index++;
//printf ("next address %d at array line %d", addr, id_index);
}
| VAR IDENT '[' INT_LIT ']'INT NEWLINE {
id_type=3; //is array
ele_type = 1; //is int
insert_symbol($2,scope,id_index,id_type, addr, yylineno, ele_type);
addr++;
id_index++;
arr_index++;
//printf ("next address %d at array line %d", addr, id_index);
}
| VAR IDENT STRING NEWLINE{
id_type = 4; //is string
ele_type=0;
insert_symbol($2,scope,id_index, id_type, addr, yylineno, ele_type);
addr++;
id_index++;
arr_index++;
//printf ("next address %d at array line %d", addr, id_index);
}
| VAR IDENT BOOL '=' TRUE NEWLINE {
printf ("TRUE\n");
id_type = 5; // is bool
ele_type=0;
insert_symbol($2,scope,id_index,id_type, addr, yylineno, ele_type);
addr++;
id_index++;
arr_index++;
//printf ("next address %d at array line %d", addr, id_index);
}
| VAR IDENT BOOL '=' FALSE NEWLINE {
printf ("FALSE\n");
id_type = 5;
ele_type=0;
insert_symbol($2,scope,id_index,id_type, addr, yylineno, ele_type);
addr++;
id_index++;
arr_index++;
//printf ("next address %d at array line %d", addr, id_index);
}
;
Change
: IDENT INC { int e = lookup_symbol($1);
printf ("IDENT (name=%s, address=%d)\n", $1, e);
printf ("INC\n");}
| IDENT DEC {int e = lookup_symbol($1);
printf ("IDENT (name=%s, address=%d)\n", $1, e);
printf ("DEC\n");}
;
Assign
: Num_assign {;}
| IDENT {int e = lookup_symbol($1);
printf ("IDENT (name=%s, address=%d)\n", $1, e);}
'=' Item {
printf ("ASSIGN\n");}
;
Item
: TRUE {printf ("TRUE\nASSIGN\n");}
| FALSE {printf ("FALSE\nASSIGN\n");}
| '"' STRING_LIT '"' {printf ("STRING_LIT %s\n", $2);}
| Num {;}
;
Num_assign
: IDENT {int e = lookup_symbol($1);
printf ("IDENT (name=%s, address=%d)\n", $1, e);}
ADD_ASSIGN Num {
printf ("ADD_ASSIGN\n");}
| IDENT {int e = lookup_symbol($1);
printf ("IDENT (name=%s, address=%d)\n", $1, e);}
SUB_ASSIGN Num {
printf ("SUB_ASSIGN\n");}
| IDENT {int e = lookup_symbol($1);
printf ("IDENT (name=%s, address=%d)\n", $1, e);}
MUL_ASSIGN Num {
printf ("MUL_ASSIGN\n");}
| IDENT {int e = lookup_symbol($1);
printf ("IDENT (name=%s, address=%d)\n", $1, e);}
QUO_ASSIGN Num {
printf ("QUO_ASSIGN\n");}
| IDENT {int e = lookup_symbol($1);
printf ("IDENT (name=%s, address=%d)\n", $1, e);}
REM_ASSIGN Num {
printf ("REM_ASSIGN\n");}
;
Num
: INT_LIT {printf ("INT_LIT %d\n", $1);}
| FLOAT_LIT { printf ("FLOAT_LIT %.6f\n", $1);} //debug: precision setting
;
%%
int main(int argc, char *argv[])
{
if (argc == 2) {
yyin = fopen(argv[1], "r");
} else {
yyin = stdin;
}
int a;
for (a=0; a<52; a++) {
my_array[a][0].type= nothing;
my_array[a][0].val.ival = -1;
}
yylineno = 0;
yyparse();
dump_symbol();
printf("Total lines: %d\n", yylineno);
fclose(yyin);
return 0;
}
static void create_symbol() {
}
static void insert_symbol(char *val ,int scope, int id_index, int data_type, int address, int line, int ele_type) {
my_array[arr_index][0].type = is_int;
my_array[arr_index][0].val.ival = id_index;
my_array[arr_index][1].type = is_char;
my_array[arr_index][1].val.cval = val;
my_array[arr_index][2].type = is_int;
my_array[arr_index][2].val.ival = data_type;
my_array[arr_index][3].type = is_int;
my_array[arr_index][3].val.ival = address;
my_array[arr_index][4].type = is_int;
my_array[arr_index][4].val.ival = line;
my_array[arr_index][5].type = is_int;
my_array[arr_index][5].val.ival = ele_type;
}
static int lookup_symbol(char *val) {
//printf ("%s\n", val);
int c=0;
int d=0;
while (my_array[c][0].type!=nothing) {
//printf ("%s\n", my_array[c][1].val.cval);
int result = strcmp(my_array[c][1].val.cval, val);
//printf("strcmp(my_array[c][1].val.cval, val) = %d\n", result);
if (result==0) {
d = my_array[c][3].val.ival;
//printf ("%d\n", d);
break;
}
c++;
}
return d;
}
static void dump_symbol() {
printf("> Dump symbol table (scope level: %d)\n", 0);
printf("%-10s%-10s%-10s%-10s%-10s%s\n",
"Index", "Name", "Type", "Address", "Lineno", "Element type");
int b=0;
char type[10];
char element[10];
int r = my_array[b][2].val.ival;
int s = my_array[b][5].val.ival;
while (my_array[b][0].type!=nothing) {
//printf ("current type: %d, %d\n", my_array[b][2].val.ival, my_array[b][5].val.ival);
if (r==1) {
strcpy (type, "int32");
}
else if (r==2) {
strcpy (type, "float32");
}
else if (r==3) {
strcpy (type, "array");
}
else if (r==4) {
strcpy (type, "string");
}
if (s==0) {
strcpy (element, "-");
}
else if (s==1) {
strcpy (element, "int32");
}
else if (s==2) {
strcpy (element, "float32");
}
//printf ("%s\n",type);
//printf ("%s\n",element);
printf("%-10d%-10s%-10s%-10d%-10d%-10s\n",
b, my_array[b][1].val.cval, type, my_array[b][3].val.ival, my_array[b][4].val.ival, element);
b++;
}
}
edit: full y.tab.h file:
/* A Bison parser, made by GNU Bison 2.7. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_YY_Y_TAB_H_INCLUDED
# define YY_YY_Y_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 {
NEWLINE = 258,
LB = 259,
RB = 260,
VAR = 261,
INC = 262,
DEC = 263,
GTR = 264,
LSR = 265,
EQL = 266,
NEQ = 267,
LAND = 268,
LOR = 269,
NOT = 270,
INT = 271,
FLOAT = 272,
BOOL = 273,
STRING = 274,
PRINTLN = 275,
PRINT = 276,
TRUE = 277,
FALSE = 278,
IF = 279,
FOR = 280,
ELSE = 281,
IFX = 282,
ELSEX = 283,
FIRST = 284,
SECOND = 285,
END = 286,
GEQ = 287,
LEQ = 288,
REM_ASSIGN = 289,
QUO_ASSIGN = 290,
MUL_ASSIGN = 291,
SUB_ASSIGN = 292,
ADD_ASSIGN = 293,
INT_LIT = 294,
FLOAT_LIT = 295,
IDENT = 296,
STRING_LIT = 297
};
#endif
/* Tokens. */
#define NEWLINE 258
#define LB 259
#define RB 260
#define VAR 261
#define INC 262
#define DEC 263
#define GTR 264
#define LSR 265
#define EQL 266
#define NEQ 267
#define LAND 268
#define LOR 269
#define NOT 270
#define INT 271
#define FLOAT 272
#define BOOL 273
#define STRING 274
#define PRINTLN 275
#define PRINT 276
#define TRUE 277
#define FALSE 278
#define IF 279
#define FOR 280
#define ELSE 281
#define IFX 282
#define ELSEX 283
#define FIRST 284
#define SECOND 285
#define END 286
#define GEQ 287
#define LEQ 288
#define REM_ASSIGN 289
#define QUO_ASSIGN 290
#define MUL_ASSIGN 291
#define SUB_ASSIGN 292
#define ADD_ASSIGN 293
#define INT_LIT 294
#define FLOAT_LIT 295
#define IDENT 296
#define STRING_LIT 297
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
/* Line 2058 of yacc.c */
#line 75 "hw2_demo.y"
int i_val;
float f_val;
char *s_val;
//struct NonTer* usage;
/* Line 2058 of yacc.c */
#line 151 "y.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_Y_TAB_H_INCLUDED */

Related

Yacc %define parse.error verbose generates error

When I try to get more out of my "syntax error", I seem to use the way described on so many websites, but all seem to create their own errors, for some reason.
I was getting standard "syntax error" on line 5 of the Input file... so I wanted to add better error handling so I can see what exactly is the issue. But
%define parse.error verbose
However, it gives me this;
error: %define variable 'parse.error' is not used
Below are my files, as long as you keep it constructive, feel free to comment on more then just the error parts, any help is welcome :)
(As long as the errors get fixed as well :P )
Thanks in advance!
lex file;
%option nounput yylineno
%{
#include "yaccTest.tab.h"
void InvalidToken();
void extern yyerror (char *s);
%}
whitespace [ \t\r\v\f]
linefeed \n
%%
";" {return SEMICOLON;}
"=" {return EQ;}
"+" {return PLUS;}
"-" {return MINUS;}
"*" {return MULTIPLY;}
"/" {return DEVIDE;}
"(" {return BO;}
")" {return BC;}
"^" {return POWER;}
"print" {return PRINT;}
[a-zA-Z][a-zA-Z0-9]* {yylval.charValue = yytext[0]; return IDENTIFIER;}
[0-9]+ {yylval.intValue = atoi(yytext); return NUMBER;}
{whitespace} {;}
. {InvalidToken();}
%%
void yyerror(char *s) {
fprintf(stderr, "\nERROR ON LINE %d : \n %s\n", yylineno, s);
exit(0);
}
void InvalidToken(){
printf("ERROR ON LINE %d : \n Invalid Token %s\n", yylineno,yytext);
exit(0);
}
int yywrap (void) {return 1;}
yacc file;
%{
#include <stdio.h>
#include <stdlib.h>
int getVariableValue(char varID);
extern int yylineno;
int varIDs[52] = {0};
int varValues[52] = {0};
%}
%define parse.lac full
%define parse.error verbose
%union YYSTYPE {int intValue; char charValue;}
%token COLON SEMICOLON ST SE EQ GE GT PLUS MINUS MULTIPLY DEVIDE BO BC CBO CBC POWER LOOP PRINT
%token <intValue> NUMBER
%token <charValue> IDENTIFIER CHAR
%type <charValue> declaration expression
%type <intValue> numval
%right EQ
%left PLUS MINUS
%left MULTIPLY DEVIDE
%left POWER
%%
declaration : IDENTIFIER EQ expression
| declaration IDENTIFIER EQ expression
;
expression : numval SEMICOLON
| PRINT BO numval BC SEMICOLON {printf("Printing");}
;
numval : NUMBER {$$ = $1;}
| NUMBER PLUS NUMBER {$$ = $1 + $3;}
| NUMBER MINUS NUMBER {$$ = $1 - $3;}
| NUMBER MULTIPLY NUMBER {$$ = $1 * $3;}
| NUMBER DEVIDE NUMBER {$$ = $1 / $3;}
| NUMBER POWER NUMBER {int i;int j = $1;for(i = 1; i < $3; i++){j=j*$1;};$$ = j;}
;
%%
int getVariableValue(char varID) {
int i, j, localTemp;
for (i=0;i<((sizeof(varIDs)/sizeof(varIDs[0])));i++) {
if (varID == varIDs[i]) {
localTemp = varValues[i];
}
}
return localTemp;
}
int setVariableValue(char varID, int varValue) {
int i, varPresent = 0;
for (i=0;i<((sizeof(varIDs)/sizeof(varIDs[0])));i++) {
if (varID == varIDs[i]) {
varValues[i] = varValue;
varPresent = 1;
}
}
if (varPresent == 0) {
for (i=0;i<((sizeof(varIDs)/sizeof(varIDs[0])));i++) {
if (&(varIDs[i]) == NULL) {
if (&(varValues[i]) == NULL) {
varIDs[i] = varID;
varValues[i] = varValue;
}
else {
missingVarIDError(varID, varValue);
}
}
else {
notEnoughStorageError(varID, varValue);
}
}
}
}
int missingVarIDError(char *id, int val){
printf("\nERROR ON LINE %d : \nIdentifier '%s' not found, but assigned location DOES have a value; %s",yylineno,id,val);
exit(0);
}
int notEnoughStorageError(char *id, int val){
printf("\nERROR ON LINE %d : \nIdentifier '%s' did not fit in StorageArray, '%3' not stored!",yylineno,id,val);
exit(0);
}
int main (void) {
return yyparse ( );
return 0;
}
Input file;
x=4;
y=2+6;
X=2;
z=5;
print(4);

Accept both integers and floats in a bison grammar

This question is attached to this post https://stackoverflow.com/questions/42848197/bison-flex-cannot-print-out-result?noredirect=1#comment72805876_42848197
this time I try to make my calculator program accepts both integers and floats numbers.
Thank you.
Here is my code
Flex:
%{
#include <stdio.h>
#include "f1.tab.h"
%}
integer [1-9][0-9]*|0
float [0-9]+\.[0-9]+
%%
{integer} { yylval.ival = atoi(yytext); return INT; }
{float} { yylval.fval = atof(yytext); return FLOAT; }
. { return yytext[0]; }
%%
Bison :
%{
#include <stdio.h>
%}
%union {
int ival;
float fval;
}
%token <ival> INT
%token <fval> FLOAT
%type <fval> exp
%type <fval> fac
%type <fval> f
%%
input: line
| input line
;
line: exp ';' { printf("%d\n", $1); };
exp: fac { $$ = $1; }
| exp '+' fac { $$ = $1 + $3; }
| exp '-' fac { $$ = $1 - $3; }
;
fac: f
| fac '*' f { $$ = $1 * $3; }
| fac '/' f { $$ = $1 / $3; }
;
f: INT | FLOAT;
%%
main(int argc, char **argv) {
yyparse();
}
yyerror(char *s) {
fprintf(stderr, "error: %s\n", s);
}
Bison tells you exactly what the problem is:
parser.y:32.4-6: warning: type clash on default action: <fval> != <ival> [-Wother]
f: INT | FLOAT;
^^^
The default action for the rule f: INT copies an ivar to an fvar without any sort of conversion (basically, copying via union). To fix it, you need to insert a conversion:
f: INT { $$ = (double)$1; }

y.tab.c: undefined reference to yylex

I am trying to run an example I found online of a calculator. But I have this error showing every time I run my gcc command. Here are the commands that I run:
flex -l calc3.l
yacc -vd calc3.y
gcc y.tab.c -lm -ll
-> at this point I got this error message:
/tmp/ccPOq58f.o : In function 'yyparse':
y.tab.c: undefined reference to 'yylex'
collect2: error: ld returned 1 exit status
Here is my code:
calc3.l
%{
#include <stdlib.h>
#include "calc3.h"
#include "y.tab.h"
void yyerror(char *);
%}
%%
[a-z] {
yylval.sIndex = *yytext - 'a';
return VARIABLE;
}
0 {
yylval.iValue = atoi(yytext);
return INTEGER;
}
[1-9][0-9]* {
yylval.iValue = atoi(yytext);
return INTEGER;
}
[-()<>=+*/;{}.] {
return *yytext;
}
">=" return GE;
"<=" return LE;
"==" return EQ;
"!=" return NE;
"while" return WHILE;
"if" return IF;
"else" return ELSE;
"print" return PRINT;
[ \t\n]+ ; /* ignore whitespace */
. yyerror("Unknown character");
%%
int yywrap(void) {
return 1;
}
here is calc3.h
typedef enum { typeCon, typeId, typeOpr } nodeEnum;
/* constants */
typedef struct {
int value; /* value of constant */
} conNodeType;
/* identifiers */
typedef struct {
int i; /* subscript to sym array */
} idNodeType;
/* operators */
typedef struct {
int oper; /* operator */
int nops; /* number of operands */
struct nodeTypeTag **op; /* operands */
} oprNodeType;
typedef struct nodeTypeTag {
nodeEnum type; /* type of node */
union {
conNodeType con; /* constants */
idNodeType id; /* identifiers */
oprNodeType opr; /* operators */
};
} nodeType;
extern int sym[26];
and here is calc3.y
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "calc3.h"
/* prototypes */
nodeType *opr(int oper, int nops, ...);
nodeType *id(int i);
nodeType *con(int value);
void freeNode(nodeType *p);
int ex(nodeType *p);
int yylex(void);
void yyerror(char *s);
int sym[26]; /* symbol table */
%}
%union {
int iValue; /* integer value */
char sIndex; /* symbol table index */
nodeType *nPtr; /* node pointer */
};
%token <iValue> INTEGER
%token <sIndex> VARIABLE
%token WHILE IF PRINT
%nonassoc IFX
%nonassoc ELSE
%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%type <nPtr> stmt expr stmt_list
%%
program:
function { exit(0); }
;
function:
function stmt { ex($2); freeNode($2); }
| /* NULL */
;
stmt:
';' { $$ = opr(';', 2, NULL, NULL); }
| expr ';' { $$ = $1; }
| PRINT expr ';' { $$ = opr(PRINT, 1, $2); }
| VARIABLE '=' expr ';' { $$ = opr('=', 2, id($1), $3); }
| WHILE '(' expr ')' stmt { $$ = opr(WHILE, 2, $3, $5); }
| IF '(' expr ')' stmt %prec IFX { $$ = opr(IF, 2, $3, $5); }
| IF '(' expr ')' stmt ELSE stmt { $$ = opr(IF, 3, $3, $5, $7); }
| '{' stmt_list '}' { $$ = $2; }
;
stmt_list:
stmt { $$ = $1; }
| stmt_list stmt { $$ = opr(';', 2, $1, $2); }
;
expr:
INTEGER { $$ = con($1); }
| VARIABLE { $$ = id($1); }
| '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, $2); }
| expr '+' expr { $$ = opr('+', 2, $1, $3); }
| expr '-' expr { $$ = opr('-', 2, $1, $3); }
| expr '*' expr { $$ = opr('*', 2, $1, $3); }
| expr '/' expr { $$ = opr('/', 2, $1, $3); }
| expr '<' expr { $$ = opr('<', 2, $1, $3); }
| expr '>' expr { $$ = opr('>', 2, $1, $3); }
| expr GE expr { $$ = opr(GE, 2, $1, $3); }
| expr LE expr { $$ = opr(LE, 2, $1, $3); }
| expr NE expr { $$ = opr(NE, 2, $1, $3); }
| expr EQ expr { $$ = opr(EQ, 2, $1, $3); }
| '(' expr ')' { $$ = $2; }
;
%%
nodeType *con(int value) {
nodeType *p;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeCon;
p->con.value = value;
return p;
}
nodeType *id(int i) {
nodeType *p;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeId;
p->id.i = i;
return p;
}
nodeType *opr(int oper, int nops, ...) {
va_list ap;
nodeType *p;
int i;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
if ((p->opr.op = malloc(nops * sizeof(nodeType *))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeOpr;
p->opr.oper = oper;
p->opr.nops = nops;
va_start(ap, nops);
for (i = 0; i < nops; i++)
p->opr.op[i] = va_arg(ap, nodeType*);
va_end(ap);
return p;
}
void freeNode(nodeType *p) {
int i;
if (!p) return;
if (p->type == typeOpr) {
for (i = 0; i < p->opr.nops; i++)
freeNode(p->opr.op[i]);
free (p->opr.op);
}
free (p);
}
void yyerror(char *s) {
fprintf(stdout, "%s\n", s);
}
int main(void) {
yyparse();
return 0;
}
If you just use
flex calc3.l
then flex produces a scanner called lex.yy.c. (I removed the -l option which was used in the original question. -l causes flex to be more compatible with certain aspects of the original lex utility, and it has no use except for compiling ancient lex scanners.)
Similarly, if you just use
yacc -vd calc3.y
the bison will produce files called y.tab.c and y.tab.h. And
gcc y.tab.c -lm -ll
will produce a file called a.out.
None of that is a good idea. It's far better to give the files meaningful names, based on the input filenames. All three of these tools understand a -o command-line flag which specifies the output name file.
So you could do this:
flex calc3.l
yacc -vd calc3.y
gcc lex.yy.c y.tab.c -lm -ll
But I'd recommend something like this:
flex -o calc3.lex.c calc3.l
bison -o calc3.tab.c -vd calc3.y
gcc -o calc3 calc3.lex.c calc3.tab.c -lm -ll
When you do this, you'll need to change the #include "y.tab.h" to #include "calc3.tab.h". (Note that if you invoke bison as bison rather than as yacc, it will automatically produce output files with names based on the grammar file. But it doesn't hurt to be explicit.)
Even better if you put it in a Makefile, or at least a script file.

Is there a better way to specify optional elements in rules of a CFG?

Consider a language and a compiler to design and develop for it.
In this language there is a particular statement that is part of the grammar: (=<identifier>). This piece can be recognized by the compiler. But spaces are allowed between the brackets and the equal sign and the identifier. So I have these possibilities:
(=<identifier>)
( = <identifier> )
(=identifier )
( =identifier )
...
Without considering the whole grammar but just the rules to handle this language feature, I have something like this (in a Bison-like syntax for grammar rules):
statement: OBRCKT EQ ID CBRCKT
| OBRCKT S EQ S ID S CBRCKT
| OBRCKT S EQ ID S CBRCKT
| OBRCKT S EQ S ID CBRCKT
| OBRCKT S EQ ID CBRCKT
| OBRCKT EQ S ID S CBRCKT
| OBRCKT EQ ID S CBRCKT
| OBRCKT EQ S ID CBRCKT
| ...
The space terminal S can appear or not. But the way rules are, I need to specify all possible combinations... Is there a better way to achieve this result?
As Jim commented, use your lexical tool to handle these cases instead of writing them into the productions of your grammar.
For example, I commonly use Flex for lexical analysis and Bison to define my grammar (probably as you have done).
You can achieve the result that you want with something like the following (this is just an example so it's pretty simple and cannot do much):
lexicalAnalyzer.l
/* lexicalAnalyzer.l
Specifications of tokens for some language.
*/
%{
%}
/*
* Definitions of regular expressions
* Note: You capture whitespace here...
*/
WSPACE [ \t\r]+ //We take care of the spaces here...
/*
* Tokens
*/
%%
"=" {
printf("TOKEN: EQ LEXEME: %s\n", yytext);
return T_EQ;
}
"(" {
printf("TOKEN: OBRCKT LEXEME: %s\n", yytext);
return T_OBRCKT;
}
")" {
printf("TOKEN: CBRCKT LEXEME: %s\n", yytext);
return T_CBRCKT;
}
"<" {
printf("TOKEN: LT LEXEME: %s\n", yytext);
return T_LT;
}
">" {
printf("TOKEN: GT LEXEME: %s\n", yytext);
return T_GT;
}
"identifier" {
printf("TOKEN: IDENT LEXEME: %s\n", yytext);
return T_IDENT;
}
{WSPACE} { }
. {
printf("TOKEN: UNKNOWN LEXEME: %s\n", yytext);
return T_UNKNOWN;
}
%%
syntaxAnalyzer.y
/*
syntaxAnalyzer.y
To create syntax analyzer:
flex file.l
bison file.y
g++ file.tab.c -o file_parser
file_parser < inputFileName
*/
/*
* Declaration section.
*/
%{
#include <stdio.h>
void printRule(const char *lhs, const char *rhs);
int yyerror(const char *s) {
printf("Error!");
}
extern "C" {
int yyparse(void);
int yylex(void);
int yywrap() {return 1;}
}
%}
/*
* Token declarations
*/
%token T_OBRCKT T_CBRCKT
%token T_LT T_GT T_EQ
%token T_IDENT T_UNKNOWN
/*
* Starting point.
*/
%start N_START
/*
* Translation rules.
*/
%%
N_START : N_STATEMENT
{
printRule("START", "STATEMENT");
printf("\n---- Completed parsing ----\n\n");
return 0;
}
;
N_STATEMENT : T_OBRCKT T_EQ T_LT T_IDENT T_GT T_CBRCKT
{
printRule("EXPR", "T_OBRCKT T_EQ T_LT T_IDENT T_GT T_CBRCKT");
}
;
%%
#include "lex.yy.c"
extern FILE *yyin;
void printRule(const char *lhs, const char *rhs) {
printf("%s -> %s\n", lhs, rhs);
return;
}
int main() {
do {
yyparse();
} while (!feof(yyin));
return 0;
}

Bison generating unexpected token when grammar shoud be expecting it and other

I am writing a compiler for a formatting language and I am writing the bison file. My grammar is correct I think but when I added a recursion rule it and then read the test source file it says that it accepts the rule for the ending tag but that the token is unexpected... The thing is though is that before I added the recursion rule (for some tags inbetween the start and end tag) it worked fine... Here are some details
This is the source file
\begin{document}
\title{test}
\author{test}
\date{21/02/1985}
\pagesetup{35, 80}
\end{document}
This is the bison file
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int yylex();
extern int yyparse();
extern FILE *yyin;
extern FILE *yyout;
extern int yylineno;
void yyerror(const char*);
int header_status(int,int,int,int,int);
// counters to check nubmer or document properties used, must all become 1
int title = 0;
int author = 0;
int date = 0;
int pgsetup = 0;
int tabsz = 0;
%}
%union{
int iVal;
char* sVal;
}
%error-verbose
%start source
%token <sVal> SLASH
%token <sVal> BLOCK_S BLOCK_E
%token <sVal> DOC LIST ENUM
%token <sVal> TITLE AUTHOR DATE PG_SETUP TAB_SZ SECTION PARAGRAPH ITEM LINE
%token <sVal> LBRACE RBRACE LPAREN RPAREN
%token <sVal> DOCUMENT DIMENSIONS DATE_VAL STRING
%token <iVal> NUMBER
%token <sVal> ERROR_UN ERROR_IL WORD
%%
source
: /* empty */
| entry_point doc_properties txt_properties exit_point
{
if ( header_status(title, author, date, pgsetup, tabsz) == 0 )
printf("\nfail\n"); //YYABORT;
}
;
entry_point
: SLASH BLOCK_S LBRACE DOC RBRACE
;
doc_properties
: /* empty */
| doc_properties header_properties
;
header_properties
: title_property { title++; }
| author_property { author++; }
| date_property { date++; }
| pg_setup_property { pgsetup++; }
| tab_sz_property { tabsz++; }
;
txt_properties
: /* empty */
;
title_property
: SLASH TITLE LBRACE STRING RBRACE
;
author_property
: SLASH AUTHOR LBRACE STRING RBRACE
;
date_property
: SLASH DATE LBRACE DATE_VAL RBRACE
;
pg_setup_property
: SLASH PG_SETUP LBRACE DIMENSIONS RBRACE
;
tab_sz_property
: SLASH TAB_SZ LPAREN NUMBER RPAREN
;
exit_point
: SLASH BLOCK_E LBRACE DOC RBRACE
;
%%
int main (int argc, char* argv[])
{
if ( argc < 2 || argc > 3)
{
fprintf(stdout, "%s: fatal error: needs one or two arguments\n\n\t%s inputFileName [outputFileName]\n\n", argv[0], argv[0]);
}
else if ( argc == 2 )
{
char* fn = (char *)calloc(strlen(argv[1])+12, sizeof(char));
strcpy(fn, argv[1]);
strcat(fn, ".output.txt");
fprintf(stderr, "%s: using default output naming: <%s>\n\n", argv[0], fn);
yyin = fopen(argv[1], "r");
yyout = fopen(fn, "w");
yyparse();
fclose(yyin);
fclose(yyout);
}
else if ( argc == 3 )
{
yyin = fopen(argv[1], "r");
yyout = fopen(argv[2], "w");
yyparse();
fclose(yyin);
fclose(yyout);
}
return 0;
}
void yyerror(const char* str)
{
fprintf(stderr,"syntax error[%d]: %s\n",yylineno, str);
}
int header_status(int title, int author, int date, int pgsetup, int tabsz)
{
if ( title == 1 && author == 1 && date == 1 && pgsetup == 1 && tabsz == 1 )
{
return 1;
}
else
{
if ( title > 1 ) fprintf(stderr,"syntax error: title property was declared more than once\n");
else if ( title < 1 ) fprintf(stderr,"syntax error: title property was not declared (all document properties must be present)\n");
if ( author > 1 ) fprintf(stderr,"syntax error: author property was declared more than once\n");
else if ( author < 1 ) fprintf(stderr,"syntax error: author property was not declared (all document properties must be present)\n");
if ( date > 1 ) fprintf(stderr,"syntax error: date property was declared more than once\n");
else if ( date < 1 ) fprintf(stderr,"syntax error: date property was not declared (all document properties must be present)\n");
if ( pgsetup > 1 ) fprintf(stderr,"syntax error: pagesetup property was declared more than once\n");
else if ( pgsetup < 1 ) fprintf(stderr,"syntax error: pagesetup property was not declared (all document properties must be present)\n");
if ( tabsz > 1 ) fprintf(stderr,"syntax error: title tabsize was declared more than once\n");
else if ( tabsz < 1 ) fprintf(stderr,"syntax error: title tabsize was not declared (all document properties must be present)\n");
return 0;
}
}
My problem I think is in
doc_properties
: /* empty */
| doc_properties header_properties
;
When I had it empty and just
\begin{document}
\end{document}
for the source file it was fine. Specifically the tokens would be
SLASH BLOCK_S LBRACE DOC RBRACE
SLASH BLOCK_E LBRACE DOC RBRACE
When I added the rule with the recursion though when it reached at the 'end' the trace would say that it accepted the rule (lexical) and then it generated a syntax error "unexpected BLOCK_E". The only thing I can think of is that it is expecting some other tag but in the recursion I have the empty as an alternative so why...
Also when I added the final tag
\begin{document}
\title{test}
\author{test}
\date{21/02/1985}
\pagesetup{35, 80}
\tabsize(4)
\end{document}
when it reached at 4 it says that is accepts the rule in the lex file and that rule
return NUMBER;
but it says unexpected $undefined, expecting NUMBER when it just said that it accepts the rule and frankly I don't think it could read anything else...
My question is for the first part though...
If it is any help this is the flex file
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "UnicTextLang.y.tab.h"
#define SAVE_S yylval.sVal = strdup(yytext)
#define SAVE_I yylval.iVal = atoi(yytext)
%}
WS [ \t\n\r]
TAG [a-zA-Z_][a-zA-Z0-9\-_]+
WORD [a-zA-Z0-9`~!##$%\^&*()\-_=+[\]{}\\|;:'",<.>/?]
NUMBER ([1-9])|([1-9][0-9])|([1-3][0-9][0-9])
DIMEN {NUMBER}{WS}*,{WS}*{NUMBER}
DAY (0[1-9])|([12][0-9])|(3[01])
MONTH (0[1-9])|(1[0-2])
YEAR (19|20)[0-9]{2}
DATE {DAY}\/{MONTH}\/{YEAR}
%option yylineno
%option noyywrap
%option noinput
%option nounput
%option debug
%x PROPERTY
%x VALUE
%x BLOCK
%x NUMBER
%%
^\\|{WS}\\ { BEGIN(PROPERTY); /* fprintf(stdout, "FLEX> BEGINING PROPERTY [%d]: %s|\n", yylineno, yytext); */ SAVE_S; return SLASH; }
{WS}?\{ { BEGIN(VALUE); /* fprintf(stdout, "FLEX> READING PROPERTY VALUE [%d]: %s|\n", yylineno, yytext); */ SAVE_S; return LBRACE; }
{WS}?\( { BEGIN(NUMBER); /* fprintf(stdout, "FLEX> READING NUMBER VALUE [%d]: %s|\n", yylineno, yytext); */ SAVE_S; return LPAREN; }
{WS} { /* fprintf(stdout, "FLEX> EATING WHITESPACE(i)\n"); */ }
[^ \t\n\r\{(\\][^ \t\n\r]+ { fprintf(stderr, "lexical error[%d]: hingeless word: %s\n", yylineno, yytext); SAVE_S; return WORD; }
. { fprintf(stderr, "lexical error[%d]: illegal character detected: %s\n", yylineno, yytext); SAVE_S; return ERROR_IL; }
<PROPERTY>begin { BEGIN(BLOCK); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return BLOCK_S; }
<PROPERTY>end { BEGIN(BLOCK); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return BLOCK_E; }
<PROPERTY>title { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return TITLE; }
<PROPERTY>author { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return AUTHOR; }
<PROPERTY>date { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return DATE; }
<PROPERTY>pagesetup { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return PG_SETUP; }
<PROPERTY>tabsize { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return TAB_SZ; }
<PROPERTY>section { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return SECTION; }
<PROPERTY>paragraph { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return PARAGRAPH; }
<PROPERTY>item { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return ITEM; }
<PROPERTY>newline { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> \n\t%s\n\n", yytext); */ SAVE_S; return LINE; }
<PROPERTY>{TAG} { BEGIN(INITIAL); fprintf(stderr, "lexical error[%d]: |%s| undefined property: expecting property\n", yylineno, yytext); SAVE_S; return ERROR_UN; }
<PROPERTY>{WS} { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> EATING WHITESPACE(p)\n"); */ }
<PROPERTY>[^ \t\n\r\{(]+ { BEGIN(INITIAL); fprintf(stderr, "lexical error[%d]: |%s| undefined property: illegal character detected\n", yylineno, yytext); SAVE_S; return ERROR_IL; }
<PROPERTY>. { fprintf(stderr, "lexical error[%d]: illegal character detected: %s\n", yylineno, yytext); SAVE_S; return ERROR_IL; }
<VALUE>{WS}*{DIMEN}{WS}* { /* fprintf(stdout, "FLEX> \n\tdims: %s\n\n", yytext); */ SAVE_S; return DIMENSIONS; }
<VALUE>{WS}*{DATE}{WS}* { /* fprintf(stdout, "FLEX> \n\tdate: %s\n\n", yytext); */ SAVE_S; return DATE_VAL; }
<VALUE>[^}]* { /* fprintf(stdout, "FLEX> \n\tstrg: %s\n\n", yytext); */ SAVE_S; return STRING; }
<VALUE>\} { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> FINISHED READING PROPERTY VALUE [%d]: %s|\n", yylineno, yytext); */ SAVE_S; return RBRACE; }
<VALUE>. { fprintf(stderr, "lexical error[%d]: illegal character detected: %s\n", yylineno, yytext); SAVE_S; return ERROR_IL; }
<NUMBER>{WS}*{NUMBER}{WS}* { /* fprintf(stdout, "FLEX> \n\tnumb: %s\n\n", yytext); */ SAVE_I; return NUMBER; }
<NUMBER>[^)]* { fprintf(stderr, "lexical error[%d]: |%s| illegal value: expecting number(1-399)\n", yylineno, yytext); SAVE_S; return STRING; }
<NUMBER>\) { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> FINISHED READING NUMBER VALUE [%d]: %s|\n", yylineno, yytext); */ SAVE_S; return RPAREN; }
<NUMBER>. { fprintf(stderr, "lexical error[%d]: illegal character detected: %s\n", yylineno, yytext); SAVE_S; return ERROR_IL; }
<BLOCK>{WS}?\{ { /* fprintf(stdout, "FLEX> READING BLOCK TYPE [%d]: %s|\n", yylineno, yytext); */ SAVE_S; return LBRACE; }
<BLOCK>{WS}*document{WS}* { /* fprintf(stdout, "FLEX> \n\tresv: %s\n\n", yytext); */ SAVE_S; return DOC; }
<BLOCK>{WS}*itemize{WS}* { /* fprintf(stdout, "FLEX> \n\tresv: %s\n\n", yytext); */ SAVE_S; return LIST; }
<BLOCK>{WS}*enumerate{WS}* { /* fprintf(stdout, "FLEX> \n\tresv: %s\n\n", yytext); */ SAVE_S; return ENUM; }
<BLOCK>[^{}]* { fprintf(stderr, "lexical error[%d]: |%s| undefined block type: expecting block type\n", yylineno, yytext); SAVE_S; return ERROR_UN; }
<BLOCK>\} { BEGIN(INITIAL); /* fprintf(stdout, "FLEX> FINISHED READING BLOCK TYPE [%d]: %s|\n", yylineno, yytext); */ SAVE_S; return RBRACE;}
<BLOCK>. { fprintf(stderr, "lexical error[%d]: illegal character detected: %s\n", yylineno, yytext); SAVE_S; return ERROR_IL; }
%%
The basic problem you have is that parser needs two-token lookahead to determine where the doc_properties end. This is because you recognize '\' as a separate token from the property string, so after seeing the input SLASH BLOCK_S with the next input token being SLASH, it doesn't know if it should reduce an empty txt_properties (anticipating a BLOCK_E after the SLASH), or shift into the header_properties rule in anticipation of matching a header property.
There are a number of what to deal with this. Perhaps the simplest would be to get rid of the SLASH token altogether, as it just serves to tell the lexer when to look for a property string. Get rid of the return SLASH; statement in the first lex action (so it doesn't return a token, but instead keeps looking for the property after the \ to return that token), and delete SLASH everywhere it appears in your grammar.
Another possibility is to unfactor the grammar to get rid of the epsilon rules (as they are what necessitate the early reductions that lead to shift/reduce conflicts). With no epsilon rules the parser can shift into a composite state where it is simultaneously recognizing multiple rules with identical prefixes on the RHS (this ability is the advantage of LR parsing over LL). To do this, you would have rules like:
source: /* empty */
| entry_point exit_point
| entry_point doc_properties exit_point
| entry_point txt_properties exit_point
| entry_point doc_properties txt_properties exit_point
;
and would change doc_properties and txt_properties to recognize 1-or-more rather than 0-or-more:
doc_properties: header_property
| doc_properties header_property
;