Getting error: follex.y:338:10: error:‘ZZ_DOTDOTDOT’ not yet declared in this scope when running TAMAR transfer learning - yacc

When I ran the TAMAR, which is a system for transfer learning using MLNs by performing mapping and revision of previously learned MLNs.
I got errors from follex.y when I ran the
make transfered-learnstruct
The errors showed as follow:
In file included from /ut-alchemy/src/parser/fol.y:6:0:
/ut-alchemy/src/parser/follex.y:205:10: error:‘ZZ_NUM’ not yet declared in this scope
return ZZ_NUM;
^
In file included from /ut-alchemy/src/parser/fol.y:6:0:
/ut-alchemy/src/parser/follex.y:214:10: error:‘ZZ_NUM’ not yet declared in this scope
return ZZ_NUM;
^
In file included from /ut-alchemy/src/parser/fol.y:6:0:
/ut-alchemy/src/parser/follex.y:223:10: error:‘ZZ_NUM’ not yet declared in this scope
return ZZ_NUM;
^
In file included from /ut-alchemy/src/parser/fol.y:6:0:
/ut-alchemy/src/parser/follex.y:232:44: error:‘ZZ_CONSTANT’ not yet declared in this scope
if (zzdomain->isConstant(yytext)) return ZZ_CONSTANT;
^
/ut-alchemy/src/parser/follex.y:233:10: error:‘ZZ_STRING’ not yet declared in this scope
return ZZ_STRING;
^
In file included from /ut-alchemy/src/parser/fol.y:6:0:
/ut-alchemy/src/parser/follex.y:245:12: error:‘ZZ_TYPE’ not yet declared in this scope
return ZZ_TYPE;
^
/ut-alchemy/src/parser/follex.y:250:12: error:‘ZZ_PREDICATE’ not yet declared in this scope
return ZZ_PREDICATE;
^
/ut-alchemy/src/parser/follex.y:255:12: error:‘ZZ_FUNCTION’ not yet declared in this scope
return ZZ_FUNCTION;
^
/ut-alchemy/src/parser/follex.y:260:12: error:‘ZZ_CONSTANT’ not yet declared in this scope
return ZZ_CONSTANT;
^
/ut-alchemy/src/parser/follex.y:263:10: error:‘ZZ_VARIABLE’ not yet declared in this scope
return ZZ_VARIABLE;
^
In file included from /ut-alchemy/src/parser/fol.y:6:0:
/ut-alchemy/src/parser/follex.y:329:10: error:‘ZZ_EQEQ’ not yet declared in this scope
return ZZ_EQEQ;
^
In file included from /ut-alchemy/src/parser/fol.y:6:0:
/ut-alchemy/src/parser/follex.y:338:10: error:‘ZZ_DOTDOTDOT’not yet declared in this scope
return ZZ_DOTDOTDOT;
The follex.y is
/* scanner for first-order language */
%{
#include "folhelper.h"
bool follexDbg = false;
//bool follexDbg = true;
%}
/* not scanning another file after current one */
%option noyywrap
ZZ_SINGLE_LINE_COMMENT ([/][/][^\r\n]*)
ZZ_MULTI_LINE_COMMENT ([/][*][^*]*[*]([*]|[^*][^*\/]*[*])*[/])
/* double ' and " to avoid string syntax highlighting in xemacs */
/*ZZ_STRING [""]([^""\\n\r] | ([\][ntbr\f''""]))*[""]*/
ZZ_STRING ([""]([^""\\\n\r]|([\\][ntbr\f''""]))*[""])
ZZ_NOT ([!])
ZZ_OR [ ]+[v][ \r\n]+
ZZ_AND [ ]+[\^][ \r\n]+
ZZ_IMPLY [=][>]
ZZ_EQUIV [<][=][>]
ZZ_EXIST [Ee][Xx][Ii][Ss][Tt]
ZZ_FORALL [Ff][Oo][Rr][Aa][Ll][Ll]
ZZ_ASTERISK [*]
ZZ_PLUS [+]
ZZ_MINUS [-]
ZZ_MINUS_OR_PLUS [+-]
ZZ_QS [?]
ZZ_EQEQ [=][=]
ZZ_EQ [=]
ZZ_DOTDOTDOT [.][.][.]
ZZ_INCLUDE [#][i][n][c][l][u][d][e]
ZZ_DIGIT ([0-9])
/* double ' to avoid string syntax highlighting in xemacs */
ZZ_ID [a-zA-z_\-][a-zA-Z0-9_\-'']*
%%
"{" {
if (follexDbg) printf("LBRACE: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
"}" {
if (follexDbg) printf("RBRACE: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
{ZZ_SINGLE_LINE_COMMENT} {
if (follexDbg) printf("SINGLE_LINE_COMMENT: %s\n", yytext);
if (yytext[strlen(yytext)-1] == '\n' || yytext[strlen(yytext)-1] == '\r')
{
++zzline;
zzcolumn = -1;
}
else
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
}
{ZZ_MULTI_LINE_COMMENT} {
if (follexDbg) printf("MULTI_LINE_COMMENT: %s\n", yytext);
int i=-1;
while (yytext[++i] != '\0')
{
if (yytext[i] == '\n' || yytext[i] == '\r')
{
++zzline;
zzcolumn = -1;
}
else
zzcolumn++;
}
zznumCharRead += strlen(yytext);
}
{ZZ_INCLUDE} {
if (follexDbg) printf("INCLUDE: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return ZZ_INCLUDE;
}
{ZZ_NOT} {
if (follexDbg) printf("NOT: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
{ZZ_OR} {
if (follexDbg) printf("OR: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add("v");
return 'v';
}
{ZZ_AND} {
if (follexDbg) printf("AND: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add("^");
return '^';
}
{ZZ_IMPLY} {
if (follexDbg) printf("IMPLY: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return ZZ_IMPLY;
}
{ZZ_EQUIV} {
if (follexDbg) printf("EQUIV: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return ZZ_EQUIV;
}
{ZZ_EXIST} {
if (follexDbg) printf("EXIST: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return ZZ_EXIST;
}
{ZZ_FORALL} {
if (follexDbg) printf("FORALL: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return ZZ_FORALL;
}
{ZZ_ASTERISK} {
if (follexDbg) printf("ASTERISK: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
{ZZ_PLUS} {
if (follexDbg) printf("PLUS: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
{ZZ_MINUS} {
if (follexDbg) printf("MINUS: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
{ZZ_QS} {
if (follexDbg) printf("QS: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
{ZZ_MINUS}?{ZZ_DIGIT}+ {
if (follexDbg) printf("INTEGER: %s (%d)\n", yytext, atoi(yytext));
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return ZZ_NUM;
}
{ZZ_MINUS}?{ZZ_DIGIT}+"."{ZZ_DIGIT}* {
if (follexDbg) printf("FLOAT: %s (%g)\n", yytext, atof(yytext));
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return ZZ_NUM;
}
{ZZ_MINUS}?{ZZ_DIGIT}+"."?{ZZ_DIGIT}*"e"{ZZ_MINUS_OR_PLUS}?{ZZ_DIGIT}+ {
if (follexDbg) printf("EXP_FLOAT: %s (%e)\n", yytext, atof(yytext));
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return ZZ_NUM;
}
{ZZ_STRING} {
if (follexDbg) printf("STRING: %s \n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
if (zzdomain->isConstant(yytext)) return ZZ_CONSTANT;
return ZZ_STRING;
}
{ZZ_ID} {
//if (follexDbg) printf("IDENTIFIER: %s\n", yytext );
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
if (zzdomain->isType(yytext))
{
if (follexDbg) printf("ZZ_TYPE: %s\n", yytext );
return ZZ_TYPE;
}
if (zzdomain->isPredicate(yytext))
{
if (follexDbg) printf("ZZ_PREDICATE: %s\n", yytext );
return ZZ_PREDICATE;
}
if (zzdomain->isFunction(yytext))
{
if (follexDbg) printf("ZZ_FUNCTION: %s\n", yytext );
return ZZ_FUNCTION;
}
if (zzdomain->isConstant(yytext))
{
if (follexDbg) printf("ZZ_CONSTANT: %s\n", yytext );
return ZZ_CONSTANT;
}
if (follexDbg) printf("ZZ_VARIABLE: %s\n", yytext );
return ZZ_VARIABLE;
}
"\n"|"\r" {
if (follexDbg)
{
if (zzparseGroundPred) printf("AT: %c\n", '#');
else printf("NEWLINE: %s", yytext);
}
++zzline;
zznumCharRead += 1;
zzcolumn = -1;
if (zzparseGroundPred) {
zzafterRtParen = false;
zztokenList.add("#");
return '#';
}
zztokenList.add(yytext);
return yytext[0];
}
"(" {
if (follexDbg) printf("LEFT PAREN: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
if (zzparseGroundPred) zzafterRtParen = false;
return yytext[0];
}
")" {
if (follexDbg) printf("RIGHT PAREN: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
if (zzparseGroundPred) zzafterRtParen = true;
return yytext[0];
}
"," {
if (follexDbg) printf("COMMA: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
{ZZ_EQ} {
if (follexDbg) printf("EQUAL: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add("=");
return '=';
}
{ZZ_EQEQ} {
if (follexDbg) printf("EQUALEQUAL: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add("==");
return ZZ_EQEQ;
}
{ZZ_DOTDOTDOT} {
if (follexDbg) printf("DOTDOTDOT: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add("...");
return ZZ_DOTDOTDOT;
}
"#" {
if (follexDbg) printf("AT: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
"." {
if (follexDbg) printf("FULLSTOP: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
[ \t]+ { /* eat up whitespace */
if (follexDbg)
{
if (zzparseGroundPred) printf("WS:\n");
}
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
if (zzparseGroundPred && zzafterRtParen) { zztokenList.add("#"); return '#'; }
}
. {
// commented out so as to allow fol.y to deal with the problem
//printf("\nERROR: Unrecognized character. %s: ln %d, col %d: %s \n",
// zzinFileName.c_str(), zzline, zzcolumn+1, yytext);
//exit(-1);
if (follexDbg) printf("Unrecognized character: %s\n", yytext);
zzcolumn += strlen(yytext);
zznumCharRead += strlen(yytext);
zztokenList.add(yytext);
return yytext[0];
}
<<EOF>> {
if (zzparseGroundPred)
{
if (zznumEofSeen == 0)
{
zznumEofSeen++;
if (follexDbg) printf("EOF returned as #:\n");
zztokenList.add("#");
return '#';
}
else
{
zzparseGroundPred = false;
zzafterRtParen = false;
zznumEofSeen = 0;
}
}
if (zznumEofSeen==0)
{
ungetc(EOF, yyin);
zznumEofSeen = 1;
if (follexDbg) printf("EOF returned as \\n:\n");
zztokenList.add("\n"); // pretend that file ends with newline
return '\n';
}
zznumEofSeen = 0;
if (follexDbg) printf("EOF %s:\n", yytext);
if (false) yyunput(1,NULL); //avoid compilation warning
fclose(yyin);
if (zzinStack.empty()) return 0;
ZZFileState fileState = zzinStack.top();
zzinFileName = fileState.inFileName_;
zznumCharRead = fileState.numCharRead_;
zzline = fileState.line_;
zzcolumn = fileState.column_;
zzinStack.pop();
FILE* previn = fileState.file_;
if (fseek(previn, zznumCharRead-1, SEEK_SET)!=0)
{
printf("\nERROR: In follex.y. Failed to seek to previous position in file "
"%s, ln %d, col %d\n", zzinFileName.c_str(), zzline, zzcolumn+1);
exit(-1);
}
yyrestart(previn);
}
%%
The fol.y is
%{
#define YYSTYPE int
#define YYDEBUG 1
#include "fol.h"
#include "follex.cpp"
// 0: no output; 1,2: increasing order of verbosity
int folDbg = 0;
//int folDbg = 1;
//int folDbg = 2;
%}
/*************************** Declarations ***************************/
// the token 'error' is declared by Bison
%token ZZ_NUM
%token ZZ_DOTDOTDOT
%token ZZ_STRING
%token ZZ_EQEQ
%token ZZ_INCLUDE
%token ZZ_PREDICATE
%token ZZ_FUNCTION
%token ZZ_CONSTANT
%token ZZ_VARIABLE
%token ZZ_TYPE
%left '-' '+'
%token ZZ_FORALL
%token ZZ_EXIST
%left ZZ_EQUIV
%left ZZ_IMPLY
%left 'v'
%left '^'
%left '!'
%left '*' '/' '%'
%glr-parser
%expect 16
%error-verbose
%%
I searched a lot, but I cannot find solution. Could someone help me solve the problems? Thanks!

The solution I found is to add the definition in the fol.h.
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
ZZ_NUM = 258,
ZZ_DOTDOTDOT = 259,
ZZ_STRING = 260,
ZZ_EQEQ = 261,
ZZ_INCLUDE = 262,
ZZ_PREDICATE = 263,
ZZ_FUNCTION = 264,
ZZ_CONSTANT = 265,
ZZ_VARIABLE = 266,
ZZ_TYPE = 267,
ZZ_FORALL = 268,
ZZ_EXIST = 269,
ZZ_EQUIV = 270,
ZZ_IMPLY = 271
};
#endif
/* Tokens. */
#define ZZ_NUM 258
#define ZZ_DOTDOTDOT 259
#define ZZ_STRING 260
#define ZZ_EQEQ 261
#define ZZ_INCLUDE 262
#define ZZ_PREDICATE 263
#define ZZ_FUNCTION 264
#define ZZ_CONSTANT 265
#define ZZ_VARIABLE 266
#define ZZ_TYPE 267
#define ZZ_FORALL 268
#define ZZ_EXIST 269
#define ZZ_EQUIV 270
#define ZZ_IMPLY 271

Related

Lex/Yacc failed to compile

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 */

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);

Searching a word in a 2d array in c programming

I am trying to set up a program that when you type /s then a movie title (ex. /s Green Mile it searches for that movie title in the movies array but my strstr function is not working. Also /a adds movie /r shows all movies in database and /q quits program.
#include <stdio.h>
#include <string.h>
main() {
char movies[1000][64];
int i;
int j = 1;
int k = 0;
int counter = 0;
char buffer[64];
char buffer2[64];
int len;
do {
printf("Enter command for movie database:\n");
fgets(buffer, 64, stdin);
if (buffer[1] == 'a') {
len = strlen(buffer);
if (buffer[len - 1] == '\n')
buffer[len - 1] = '\0';
for(i=3; i<sizeof(buffer); i++) {
movies[counter][k] = buffer[i];
k++;
}
printf("You have chosen to enter a movie in the database.\n");
printf("The movie added to the database is: %s\n", &movies[counter][0]);
counter++;
k = 0;
}
if (buffer[1] == 'q') {
printf("You have chosen to quit.\n");
printf("Goodbye.\n");
}
if (buffer[1] == 's') {
for(i=2; i<sizeof(buffer); i++) {
buffer2[k] = buffer[i];
k++;
}
for (i = 0; i < counter; i++) {
if (strstr(movies[i], buffer2) != NULL) {
printf("Found %s in position %d,%s\n", buffer2, i + 1, movies[i]);
printf("Index of Movie is %d.\n", i + 1);
}
}
k = 0;
}
if (buffer[1] == 'r') {
printf("You have choosen to report movies in database\n");
printf("These are the movies you have watched:\n");
for( i = 0; i < counter; i++ ) {
printf("%d: %s\n", j, &movies[i][0]);
j++;
}
printf("\n");
j = 1;
}
} while (buffer[1] != 'q');
}
Revised code.
#include <stdio.h>
#include <string.h>
main() {
char movies[1000][64];
int counter = 0;
char buffer[64];
char * movieTitle = &buffer[3];
while(true) {
printf("Enter command for movie database:\n");
fgets(buffer, 64, stdin);
//replace terminator every time
int len = strlen(buffer);
if (buffer[len - 1] == '\n')
buffer[len - 1] = '\0';
if(strstr(buffer, "/a") && counter < 1000) {
strcpy(movies[counter], movieTitle);
printf("You have chosen to enter a movie in the database.\n");
printf("The movie added to the database is: %s\n", &movies[counter][0]);
counter++;
}
else if (strstr(buffer, "/s")) {
for (int i = 0; i < counter; i++) {
if (strcmp(movies[i], movieTitle) == 0) {
printf("Found %s in position %d,%s\n", movieTitle, i + 1, movies[i]);
printf("Index of Movie is %d.\n", i + 1);
}
}
}
else if (strstr(buffer, "/r")) {
printf("You have choosen to report movies in database\n");
printf("These are the movies you have watched:\n");
for( i = 0; i < counter; i++ ) {
printf("%d: %s\n", i + 1, &movies[i][0]);
}
printf("\n");
}
else if (strstr(buffer, "/q")) {
printf("You have chosen to quit.\n");
printf("Goodbye.\n");
break;
}
else {
printf("unrecognized command");
}
}
}

Reading file using fscanf in C

I have a fixed format text file to be read in my C program.
The format of the text file is as below:
w 400341a0
r dfcfa8
w 7b034dd4
The first character is always w or r, while the second element is a 32bit hex digit.
I have written the code as below to read this file line by line :
int main (int argc, char *argv[])
{
FILE* file_ptr;
char rw;
uint32_t address;
int file_read;
uint32_t file_line_ctr = 1;
#if(MODE == DEBUG)
{
printf("DEBUG_MODE\n ");
}
#else
{
/*Do Nothing*/
}
#endif
file_ptr = fopen(argv[10], "r");
if (file_ptr == NULL)
{
printf("Can't Open File\n");
}
else
{
printf("File Opened Successfully\n");
}
file_read = fscanf(file_ptr, "%c %x" , &rw, &address);
printf("%c %x \n", rw, address);
while (file_read!= EOF)
{
file_read = fscanf(file_ptr, "%c %x" , &rw, &address);
file_line_ctr ++;
printf("%c %x \n", rw, address);
}
fclose(file_ptr);
printf("File Length = %d \n", file_line_ctr);
return 1;
}
I get the output in the below format for a file with 100000 entries:
w 400341a0
400341a0
r dfcfa8
dfcfa8
w 7b034dd4
7b034dd4
File Length = 200000
Evidently, I am reading the entries twice for some reason, as well as printing them twice.
Can someone figure out why is it so ?
Well. Here is a fix
#include <stdlib.h>
#include <stdio.h>
int main (int argc, char *argv[])
{
FILE* file_ptr;
char rw;
unsigned int address;
int file_read=0;
unsigned int file_line_ctr = 1;
#if(MODE == DEBUG)
{
printf("DEBUG_MODE\n ");
}
#else
{
/*Do Nothing*/
}
#endif
file_ptr = fopen(argv[1], "r");
if (file_ptr == NULL)
{
printf("Can't Open File\n");
}
else
{
printf("File Opened Successfully\n");
}
/*
file_read = fscanf(file_ptr, "%c %x " , &rw, &address);
printf("%c %x \n", rw, address);
*/
while (true)
{
file_read = fscanf(file_ptr, "%c %x " , &rw, &address);
if (file_read == EOF)
break;
file_line_ctr ++;
printf("%c %x \n", rw, address);
}
fclose(file_ptr);
printf("File Length = %d \n", file_line_ctr);
return 1;
}
You will notice that I have added a space after the %x to eat the newlines as white space.
I have also modified your while loop a little to stop the last line being repeat printed. Crude. But it will work until you can rethink the logic. The while (true) may not work with all compilers. I used while (1). Which is non standard but worked for me.

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
;