bisonc++ - No production rules? - bisonc++

I'm trying to compile the following with bisonc++:
%baseclass-preinclude <iostream>
%lsp-needed
%token NUMBER COMMENT KEYWORD VARIABLE LOGICAND LOGICOR LOGICEQUALS DOUBLELESSER
%token DOUBLEGREATER MOD LESSER GREATER OPEN CLOSE NEGATE CURLYOPEN CURLYCLOSE SEMICOLON
%left EQUALS
%left PLUS MINUS
%left TIMES
%left DIVISION
%%
start:
expressions
{
std::cout << "start -> expressions" << std::endl;
}
;
expressions:
// empty
{
std::cout << "expressions -> epsylon" << std::endl;
}
|
exp expressions
{
std::cout << "expressions -> exp expressions" << std::endl;
}
;
exp:
NUMBER
{
std::cout << "exp -> NUMBER" << std::endl;
}
|
COMMENT
{
std::cout << "exp -> COMMENT" << std::endl;
}
|
exp LOGICAND exp
{
std::cout << "exp -> exp LOGICAND exp" << std::endl;
}
|
exp LOGICOR exp
{
std::cout << "exp -> exp LOGICOR exp" << std::endl;
}
|
exp LOGICEQUALS exp
{
std::cout << "exp -> exp LOGICEQUALS exp" << std::endl;
}
|
exp DOUBLELESSER exp
{
std::cout << "exp -> exp DOUBLELESSER exp" << std::endl;
}
|
exp DOUBLEGREATER exp
{
std::cout << "exp -> exp DOUBLEGREATER exp" << std::endl;
}
|
exp PLUS exp
{
std::cout << "exp -> exp PLUS exp" << std::endl;
}
|
exp MINUS exp
{
std::cout << "exp -> exp MINUS exp" << std::endl;
}
|
exp TIMES exp
{
std::cout << "exp -> exp EQUAL exp" << std::endl;
}
|
exp EQUAL exp
{
std::cout << "exp -> exp EQUAL exp" << std::endl;
}
|
exp DIVISION exp
{
std::cout << "exp -> exp DIVISION exp" << std::endl;
}
|
exp MOD exp
{
std::cout << "exp -> exp MOD exp" << std::endl;
}
|
exp LESSER exp
{
std::cout << "exp -> exp LESSER exp" << std::endl;
}
|
exp GREATER exp
{
std::cout << "exp -> exp GREATER exp" << std::endl;
}
|
OPEN exp CLOSE
{
std::cout << "exp -> OPEN exp CLOSE" << std::endl;
}
|
NEGATE exp
{
std::cout << "exp -> NEGATE exp" << std::endl;
}
|
CURLYOPEN exp CURLYCLOSE
{
std::cout << "exp -> CURLYOPEN exp CURLYCLOSE" << std::endl;
}
|
exp SEMICOLON
{
std::cout << "exp -> SEMICOLON" << std::endl;
}
|
KEYWORD VARIABLE SEMICOLON
{
std::cout << "exp -> KEYWORD VARIABLE SEMICOLON" << std::endl;
}
;
However, it keeps returning with the error
') encountered.1] Line 1: unrecognized input (`
': identifier or character-constant expected.
[bead.y: fatal] Line 23: No production rules
134950080
I obviously have some production rules and have no idea what I'm doing wrong. I've copied most of the code from another working example and modified it to my liking. What is wrong?

Your files are not UNIX conform (calculate.l and calculate.y)
If you're operating on Windows and you use Nodepad++, just do the following:
Edit/EOL conversion/UNIX format
Encoding/Convert your files to UTF-8 without BOM
Save and recompile with flex and bisonc++
Hope this helps

I had the same problem, and my teacher showed me, that some of the windows editors create invisible trash in your file, so edit your file with the terminal.
pico yourfile.y
Hit an Enter before the first line, than erase it.
Save
Thats it!

Related

How to solve yacc error "... has no declared type"

I have problem on Yacc/Bison.
We use Kotlin grammar.
This is my code :
%token BOOL
%token BREAK
%token CHAR
%token CONTINUE
%token DO
%token ENUM
%token EXTERN
%token FALSE
%token FLOAT
%token FOR
%token FN
%token IN
%token INT
%token LET
%token LOOP
%token MATCH
%token MUT
%token PRINT
%token PRINTLN
%token PUB
%token RETURN
%token SELF
%token STATIC
%token STR
%token STRUCT
%token TRUE
%token USE
%token WHERE
%token IF
%token ELSE
%token <Token> INTEGER
%token <Token> STRING
%token <Token> REAL
%token <Token> ID
%type <Token> arrDec type expression integerExpr realExpr boolExpr stringExpr functionInvoc
varDec: LET MUT ID ':' type ';' {
Trace("Reducing to varDec Form LET MUT ID ':' type ';'\n");
variableEntry ve = ve_basic_notInit($3.stringVal, $5.tokenType, false);
if (symTabs.isNowGlobal())
{
ve.isGlobal = true;
printTabs();
if (ve.type== T_INT)
fp << "field static int " << ve.name << endl;
else if (ve.type == T_BOOL)
fp << "field static int " << ve.name << endl;
}
else
{
ve.isGlobal = false;
ve.stackIndex = nowStackIndex;
nowStackIndex++;
}
if (!symTabs.addVariable(ve))
yyerror("Re declaration.");
}
| LET MUT ID '=' expression ';' {
Trace("Reducing to varDec Form LET MUT ID '=' expression ';'\n");
variableEntry ve = ve_basic($3.stringVal, $5.tokenType, false);
if ($5.tokenType == T_INT)
ve.data.intVal = $5.intVal;
else if ($5.tokenType == T_FLOAT)
ve.data.floatVal = $5.floatVal;
else if ($5.tokenType == T_BOOL)
ve.data.boolVal = $5.boolVal;
else if ($5.tokenType == T_STRING)
ve.data.stringVal = $5.stringVal;
if (symTabs.isNowGlobal())
{
ve.isGlobal = true;
printTabs();
if (ve.type == T_INT)
fp << "field static int " << ve.name << " = " << ve.data.intVal << endl;
else if (ve.type == T_BOOL)
fp << "field static int " << ve.name << " = " << ve.data.boolVal << endl;
}
else
{
ve.isGlobal = false;
ve.stackIndex = nowStackIndex;
nowStackIndex++;
printTabs();
if (ve.type == T_INT)
fp << "istore " << ve.stackIndex << endl;
else if (ve.type == T_BOOL)
fp << "istore " << ve.stackIndex << endl;
}
if (!symTabs.addVariable(ve))
yyerror("Re declaration.");
}
| LET MUT ID ':' type '=' expression ';' {
Trace("Reducing to varDec Form LET MUT ID ':' type '=' expression ';'\n");
variableEntry ve = ve_basic($3.stringVal, $5.tokenType, false);
if ($5.tokenType == T_FLOAT && $7.tokenType == T_INT)
ve.data.floatVal = $7.intVal;
else if ($5.tokenType != $7.tokenType)
yyerror("expression is not equal to expression");
else if ($7.tokenType == T_INT)
ve.data.intVal = $7.intVal;
else if ($7.tokenType == T_FLOAT)
ve.data.floatVal = $7.floatVal;
else if ($7.tokenType == T_BOOL)
ve.data.boolVal = $7.boolVal;
else if ($7.tokenType == T_STRING)
ve.data.stringVal = $7.stringVal;
if (symTabs.isNowGlobal())
{
ve.isGlobal = true;
printTabs();
if (ve.type == T_INT)
fp << "field static int " << ve.name << " = " << ve.data.intVal << endl;
else if (ve.type == T_BOOL)
fp << "field static int " << ve.name << " = " << ve.data.boolVal << endl;
}
else
{
ve.isGlobal = false;
ve.stackIndex = nowStackIndex;
nowStackIndex++;
printTabs();
if (ve.type == T_INT)
fp << "istore " << ve.stackIndex << endl;
else if (ve.type == T_BOOL)
fp << "istore " << ve.stackIndex << endl;
}
if (!symTabs.addVariable(ve))
yyerror("Re declaration.");
}
| LET MUT ID ';' {
Trace("Reducing to varDec Form LET MUT ID ';'\n");
variableEntry ve = ve_basic_notInit($3.stringVal, T_INT, false);
if (symTabs.isNowGlobal())
{
ve.isGlobal = true;
printTabs();
fp << "field static int " << ve.name << endl;
}
else
{
ve.isGlobal = false;
ve.stackIndex = nowStackIndex;
nowStackIndex++;
}
if (!symTabs.addVariable(ve))
yyerror("Re declaration.");
}
;
I didn't paste them all.
The errors are here.
I don't know how to fix them.
yacc.y:188.33-34: error: symbol ID is used, but is not defined as a token and has no rules
varDec: LET MUT ID ':' type ';' {
^^
yacc.y:191.173-174: error: $3 of ‘varDec’ has no declared type
variableEntry ve = ve_basic_notInit($3.stringVal, $5.tokenType, false);
^^
yacc.y:216.165-166: error: $3 of ‘varDec’ has no declared type
variableEntry ve = ve_basic($3.stringVal, $5.tokenType, false);
^^
yacc.y:256.165-166: error: $3 of ‘varDec’ has no declared type
variableEntry ve = ve_basic($3.stringVal, $5.tokenType, false);
^^
yacc.y:300.173-174: error: $3 of ‘varDec’ has no declared type
variableEntry ve = ve_basic_notInit($3.stringVal, T_INT, false);
Please help me solve problem, thanks.

FLEX/YACC program not behaving as expected : can't grab int value from sequence of ints

I am trying to build a parser that takes a list of strings in the following format and performs either an addition or multiplication of all of its elements :
prod 5-6_
sum _
sum 5_
sum 5-6-7_
$
Should print the following to the screen :
prod = 30
sum = 0
sum = 5
sum = 18
What I am actually getting as output is this :
prod = 0
sum = 0
sum = 5
sum = 5
My lex file looks like this :
%{
#include <iostream>
#include "y.tab.h"
using namespace std;
extern "C" int yylex();
%}
%option yylineno
digit [0-9]
integer {digit}+
operator "sum"|"prod"
%%
{integer} { return number; }
{operator} { return oper; }
"-" { return '-'; }
"_" { return '_'; }
"$" { return '$'; }
\n { ; }
[\t ]+ { ; }
. { cout << "unknown char" << endl; }
%%
and my yacc file looks like this :
%token oper
%token number
%token '-'
%token '_'
%token '$'
%start valid
%{
#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define YYSTYPE int
extern FILE *yyin;
extern char yytext[];
extern "C" int yylex();
int yyparse();
extern int yyerror(char *);
char op;
%}
%%
valid : expr_seq endfile {}
| {}
;
expr_seq : expr {}
| expr_seq expr {}
;
expr : op sequence nl {if (op == '+') cout << "sum = " ; else cout << "prod = ";}
| op nl {if (op == '+') cout << "sum = 0"; else cout <<"prod = 1";}
;
op : oper { if (yytext[0] == 's') op = '+'; else op = '*';}
;
sequence : number { $$ = atoi(yytext);}
| sequence '-' number { if (op == '+') $$ = $1 + $3; else $$ = $1 * $3;}
;
nl : '_' { cout << endl;}
;
endfile : '$' {}
;
%%
int main(int argc, char *argv[])
{
++argv, --argc;
if(argc > 0) yyin = fopen(argv[0], "r");
else yyin = stdin;
yyparse();
return 0;
}
int yyerror(char * msg)
{
extern int yylineno;
cerr << msg << "on line # " << yylineno << endl;
return 0;
}
My reasoning for the yacc logic is as follows :
a file is valid only if it contains a sequence of expressions followed by the endfile symbol.
a sequence of expressions is a single expression or several expressions.
an expression is either an operator followed by a new line, OR an operator, followed by a list of numbers, followed by a new line symbol.
an operator is either 'sum' or 'prod'
a list of numbers is either a number or several numbers separated by the '-' symbol.
From my perspective this should work, but for some reason it doesn't interpret the sequence of numbers properly after the first element. Any tips would be helpful.
Thanks
You must not use yytext in your yacc actions. yytext is only valid during a scanner action, and the parser often reads ahead to the next token. (In fact, yacc always reads the next token. Bison sometimes doesn't, but it's not always easily predictable.)
You can associate a semantic value with every token (and non-terminal), and you can reference these semantic values using $1, $2, etc. in your yacc actions. You can even associate semantic values of different types to different grammar symbols. And if you use bison -- and you probably are using bison -- you can give grammar symbols names to make it easier to refer to their semantic values.
This is all explained in depth, with examples, in the bison manual.
The solution that worked was simply to change the following lines :
sequence : number { $$ = atoi(yytext);}
| sequence '-' number { if (op == '+') $$ = $1 + $3; else $$ = $1 * $3;}
;
to this :
sequence : number { $$ = atoi(yytext);}
| sequence '-' number { if (op == '+') $$ = $1 + atoi(yytext); else $$ = $1 * atoi(yytext);}
;

Syntax error while parsing file using flex and bison

I am parsing the following file:
BEGIN BLOCK BLK_ROWDEC
NAME cell_rowdec
SIZE UNI_rowdecSize
ITERATE itr_rows
DIRECTION lgDir_rowdec
STRAP STRD1,STRD3,STRD2
WRAP WRD1
VIA VIAB,VIAC,VIAD
ENDS BLK_ROWDEC
My flex and bison file are as follows:
lexa.l
%{
#include <iostream>
#include <stdio.h>
const char s[2] = " ";
#include "yacc.tab.h"
char *token;
#define YY_DECL extern "C" int yylex()
int line_num = 1;
using namespace std;
%}
DOT "."
COLON ":"
SEMICOLON ";"
COMMA ","
ANGLE_LEFT "<"
ANGLE_RIGHT ">"
AT "#"
EQUAL "="
SQUARE_OPEN "["
SQUARE_CLOSE [^\\]"]"
OPENBRACE "\("
CLOSEBRACE "\)"
QUOTE "\""
QUOTE_OPEN "\""
QUOTE_CLOSE [^\\]"\""
SPACE " "
TAB "\t"
CRLF "\r\n"
QUOTED_PAIR "\\"[^\r\n]
DIGIT [0-9]
ALPHA [a-zA-Z]
QTEXT [0-9a-zA-Z!#$%&'()*+,\-.\/:;<=>?#\[\]^_`{|}~]
%%
[ \t] ;
^BEGIN(.*)\r?\n+\s*BEGIN(.*) { printf("\nError : two continous BEGIN is not allowed : "); }
^ENDS(.*)\r?\n+\s*ENDS(.*) { printf("\nError : two continous END is not allowed : \n"); }
NAME { yylval.sval = strdup(yytext);
return TOK_NAME; }
SIZE { yylval.sval = strdup(yytext);
return TOK_SIZE; }
ITERATE { yylval.sval = strdup(yytext);
return TOK_ITERATE; }
DIRECTION { yylval.sval = strdup(yytext);
return TOK_DIRECTION; }
STRAP { yylval.sval = strdup(yytext);
return TOK_STRAP; }
WRAP { yylval.sval = strdup(yytext);
return TOK_WRAP; }
VIA { yylval.sval = strdup(yytext);
return TOK_VIA; }
ENDS { yylval.sval = strdup(yytext);
return TOK_END; }
BEGIN { yylval.sval = strdup(yytext);
return TOK_BEGIN; }
BLOCK { yylval.sval = strdup(yytext);
return TOK_BLOCK; }
[a-zA-Z0-9_,]+ { yylval.sval = strdup(yytext);
return TOK_STRING; }
{SPACE}* { return TOK_SPACE; }
^ENDS(.*)$ {}
^{CRLF} { return TOK_EMPTY_LINE; }
{CRLF} {}
. {}/* ignore unknown chars */
\n { ++line_num; return ENDL; }
yacca.y
%{
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdio.h>
#define YYDEBUG 1
using namespace std;
extern "C" int yylex();
extern "C" FILE *yyin;
extern int line_num;
void yyerror(const char* s);
%}
// Symbols.
%union
{
char* sval;
};
%token <sval> TOK_NAME
%token <sval> TOK_SIZE
%token <sval> TOK_STRING
%token <sval> TOK_ITERATE
%token <sval> TOK_DIRECTION
%token <sval> TOK_STRAP
%token <sval> TOK_WRAP
%token <sval> TOK_VIA
%token <sval> TOK_EMPTY_LINE
%token <sval> TOK_BLOCK
%token <sval> TOK_LINE
%token <sval> TOK_BEGIN
%token <sval> TOK_END
%token TOK_SPACE
%token END ENDL
%%
language : program ;
program : block
| program block
;
block : TOK_BEGIN TOK_BLOCK TOK_SPACE TOK_STRING blockcontents TOK_END TOK_SPACE TOK_STRING
{
cout << endl << "SHAILAVI" << $4 << " ";
}
;
blockcontents : item
| blockcontents item
;
item : TOK_SPACE TOK_NAME TOK_SPACE TOK_STRING
{
cout << endl << "Value:" << $2 << "->" << $4 << " ";
}
| TOK_SPACE TOK_SIZE TOK_SPACE TOK_STRING { cout << $2 << "->" << $4 << " "; }
| TOK_SPACE TOK_ITERATE TOK_SPACE TOK_STRING { cout << $2 << "->" << $4 << " "; }
| TOK_SPACE TOK_DIRECTION TOK_SPACE TOK_STRING { cout << $2 << "->" << $4 << " " << endl; }
| TOK_SPACE TOK_STRAP TOK_SPACE TOK_STRING { cout << "ref:" << $2 << "->" << $4 << " "; }
| TOK_SPACE TOK_WRAP TOK_SPACE TOK_STRING { cout << $2 << "->" << $4 << " "; }
| TOK_SPACE TOK_VIA TOK_SPACE TOK_STRING { cout << $2 << "->" << $4 << " " << endl; }
;
%%
int main(void) {
FILE * pt = fopen("file", "r" );
if(!pt)
{
cout << "Bad Input.Noexistant file" << endl;
return -1;
}
yyin = pt;
do
{
yydebug = 1;
yyparse();
}while (!feof(yyin));
}
void yyerror(const char *s) {
cout << "parse error on line " << line_num << "! Message: " << s << endl;
exit(-1);
}
#include "lex.yy.c"
Compilation steps:
flex lexa.l
bison -d yacca.y
g++ yacca.tab.c -lfl -o scanner.exe
At the time of execution it gives syntax error near blockcontents
Please help me to identify the mistake I have done.
Thank You so much.
It took me a while, but I've found the flaw.
In your lexer, you skip all sequences of tabs and blanks (first rule).
But your parser expects white space every now and then. Hence the syntax error.
Since you don't do anything with the white space, simply eat them within the lexer (as you already do now actually, but it is better to eliminate the {SPACE}* rule too) and eliminate the TOK_SPACE in the parser.
---- edit to give some hints ----
What I did to track down the bug is:
make the lexer verbose
I added (hash signs omitted; it confuses the renderer for some reason)
#ifdef DEBUG
#define RETURN(x) cerr << "\n--> found " << #x << "\n"; return x;
#else
#define RETURN(x) return x;
#endif
and replaced all "return something" by RETURN(something)
I compile the bison/flex files separately and link them afterwards
flex lexa.l && \
bison -d yacca.y && \
g++ -c -DDEBUG -I . lex.yy.c && \
g++ -c -I . yacca.tab.c && \
g++ lex.yy.o yacca.tab.o -o scanner
(working on linux here)
As requested the working example
%{
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdio.h>
#define YYDEBUG 1
using namespace std;
extern "C" int yylex();
extern "C" FILE *yyin;
extern int line_num;
void yyerror(const char* s);
%}
// Symbols.
%union
{
char* sval;
};
%token TOK_NAME
%token TOK_SIZE
%token TOK_STRING
%token TOK_ITERATE
%token TOK_DIRECTION
%token TOK_STRAP
%token TOK_WRAP
%token TOK_VIA
%token TOK_EMPTY_LINE
%token TOK_BLOCK
%token TOK_LINE
%token TOK_BEGIN
%token TOK_END
%token END ENDL
%%
language : program ;
program : block
| program block
;
block : TOK_BEGIN TOK_BLOCK TOK_STRING blockcontents TOK_END TOK_STRING
{
cout << endl << "SHAILAVI" << $3 << " ";
}
;
blockcontents : item
| blockcontents item
;
item : TOK_NAME TOK_STRING { cout << endl << "Value:" << $1 << "->" << $2 << " "; }
| TOK_SIZE TOK_STRING { cout << $1 << "->" << $2 " << $2 " << $2 " << $2 << " "; }
| TOK_WRAP TOK_STRING { cout << $1 << "->" << $2 << " "; }
| TOK_VIA TOK_STRING { cout << $1 << "->" << $2 << " " << endl; }
;
%%
int main(void) {
FILE * pt = fopen("./input", "r" );
if(!pt)
{
cout << "Bad Input.Nonexistent file" << endl;
return -1;
}
yyin = pt;
do
{
yydebug = 1;
yyparse();
}while (!feof(yyin));
}
void yyerror(const char *s) {
cout << "parse error on line " << line_num << "! Message: " << s << endl;
exit(-1);
}
extern "C" int yywrap()
{
return (1 == 1);
}
And the lexer
%{
#include
#include
const char s[2] = " ";
#include "yacca.tab.h"
char *token;
#define YY_DECL extern "C" int yylex()
int line_num = 1;
#ifdef DEBUG
#define RETURN(x) cerr << "\n--> found " << #x << "\n"; return x;
#else
#define RETURN(x) return x;
#endif
using namespace std;
%}
DOT "."
COLON ":"
SEMICOLON ";"
COMMA ","
ANGLE_LEFT ""
AT "#"
EQUAL "="
SQUARE_OPEN "["
SQUARE_CLOSE [^\\]"]"
OPENBRACE "\("
CLOSEBRACE "\)"
QUOTE "\""
QUOTE_OPEN "\""
QUOTE_CLOSE [^\\]"\""
SPACE " "
TAB "\t"
CRLF "\r\n"
QUOTED_PAIR "\\"[^\r\n]
DIGIT [0-9]
ALPHA [a-zA-Z]
QTEXT [0-9a-zA-Z!#$%&'()*+,\-.\/:;?#\[\]^_`{|}~]
/* [ \t] ; */
%%
^BEGIN(.*)\r?\n+\s*BEGIN(.*) { printf("\nError : two continous BEGIN is not allowed : "); }
^ENDS(.*)\r?\n+\s*ENDS(.*) { printf("\nError : two continous END is not allowed : \n"); }
NAME { yylval.sval = strdup(yytext);
RETURN(TOK_NAME); }
SIZE { yylval.sval = strdup(yytext);
RETURN(TOK_SIZE); }
ITERATE { yylval.sval = strdup(yytext);
RETURN(TOK_ITERATE); }
DIRECTION { yylval.sval = strdup(yytext);
RETURN(TOK_DIRECTION); }
STRAP { yylval.sval = strdup(yytext);
RETURN(TOK_STRAP); }
WRAP { yylval.sval = strdup(yytext);
RETURN(TOK_WRAP); }
VIA { yylval.sval = strdup(yytext);
RETURN(TOK_VIA); }
ENDS { yylval.sval = strdup(yytext);
RETURN(TOK_END); }
BEGIN { yylval.sval = strdup(yytext);
RETURN(TOK_BEGIN); }
BLOCK { yylval.sval = strdup(yytext);
RETURN(TOK_BLOCK); }
[a-zA-Z0-9_,]+ { yylval.sval = strdup(yytext); RETURN(TOK_STRING); }
^ENDS(.*)$ {}
^{CRLF} { RETURN(TOK_EMPTY_LINE); }
{CRLF} {}
. {}/* ignore unknown chars */
\n { ++line_num; /* RETURN(ENDL); */ }
There's only one problem left. It doesn't really like the EOF. I'll leave that as an exercise.

Check if char contains a number, dash or parentheses

Given char how can I check if it is either numeric, contains a dash - or contains a left or right brace? ()
Something like this.
char ch = ... // some char
If (ch == '-' || ch == '{' || ch == '}' || (ch >= '0' && ch <= '9'))
If you give the parameters than you can choose which character you would like for example:
char ch = "-";
cout << "Enter date (month-day-year): " << endl;
cin << month << ch << day << ch << year;
cout << month << ch << day << ch << year << endl;

BIson parsing function and parameters in wrong order

I am writing a parser with flex and bison and so far have these tokens for flex:
[ \t\n] ;
(x[0-9]+) {
yylval.var = strdup(yytext);
return VARIABLE;
}
~(x[0-9]+) {
yylval.var = strdup(yytext);
return NEG_VARIABLE;
}
[a-zA-Z0-9]+ {
yylval.name = strdup(yytext);
return NAME;
}
~[a-zA-Z0-9]+ {
yylval.name = strdup(yytext);
return NEG_NAME;
}
[\{\},\(\)] { return yytext[0];}
. ;
and these parse rules for bison are:
fol:
clauses {cout << "Done with file"<<endl;}
;
clauses:
clauses clause
| clause
;
clause:
startc terms endc
;
startc:
'{' {cout << "Bison found start of clause" << endl;}
;
endc:
'}' {cout << "Bison found end of clause" << endl;}
;
function:
NAME startfun endfun {cout << "Bison found a function " << $1 << endl;}
|NEG_NAME startfun endfun {cout << "Bison found a negative function " << $1 << endl;}
;
startfun:
'(' {cout << "Bison found start of params" << endl;}
;
endfun:
terms ')' {cout << "Bison found a function end" << endl;}
;
terms:
terms ',' term
| term
;
term:
VARIABLE {cout << "Bison found a variable "<< $1 << endl;}
| NEG_VARIABLE {cout << "Bison found a negative variable " << $1 << endl;}
| NAME {cout << "Bison found a constant " << $1 << endl;}
|function
;
Now it all works great except that when it parses a function it first parses the parameters
and parens and then gives me the function name at the end. I can work around this, but it makes my life harder since I am storing functions as disjoint sets and I would need to keep a list of the parameters until I can get the name of the function to create the root and then union them in instead of creating it directly.
Can anyone show me how to get Bison to give me the function name before the parameters? I have been trying for over an hour with no luck.
What do you mean by "give me the function name before the parameters"? Currently you don't print the function name until after you see the endfun and reduce the function rule, which is after the various parameter rules. The usual technique is to have the terms rules produce a list of things that can then be used in the function rule:
terms: terms ',' term { $$ = append_list($1, $3); }
| term { $$ = create_singleton_list($1); }
;
term: VARIABLE { $$ = new VariableTerm($1); }
...
Alternately, if you just want to print things out, you can have a rule that is reduced as soon as you see a function name:
function: funcname startfun endfun {cout << "Bison ending a function " << $1 << endl;}
;
funcname: NAME { cout << "Starting a function " << ($$ = $1) << endl; }
| NEGNAME { cout << "Starting a negative function " << ($$ = $1) << endl; }
;

Resources