So yea, my Compiler Theory class. We're supposed to demo our compiler tomorrow, but I'm getting some damned errors that I don't know how to get rid of.
Errors:
parser.tab.c:1908: error: 'yyerror' was not declared in this scope
parser.tab.c:2054: error: 'yyerror' was not declared in this scope
My problem here is this: parser.tab.c is generated by Bison from my parser.y file. As far as I can see, I don't have any errors in there that would cause this, let alone an issue with scope.
Parser.y (Bison)
/* starter parser */
%{
#include <stdio.h>
#include <string.h>
#include "lex.yy.c"
#include "Sym_Table.c"
int depth1 = 0;
int stackPointer = -2;
char *start = "main";
char *kindOne, *kindTwo;
int stackPointerOne, stackPointerTwo;
char *tempKind;
struct entry *data1, *data2;
%}
%union {
int value;
struct entry *s;
char* str;
}
/* declare tokens */
%token ID
%token INT_LITERAL STR_LITERAL FLT_LITERAL
%token NUMBER INT FLOAT
%token RETURN IF WHILE ELSE
%token CIN COUT STREAMIN STREAMOUT
%token ENDL
%token ADD SUB
%token MUL DIV MOD
%token LT GT LTE GTE EQUAL NOT_EQUAL
%token INC DEC
%token AND OR
%token ASSIGN_OP
%token LPAREN RPAREN LBRACKET RBRACKET LBRACE RBRACE
%token SEMI COMMA NOT
%token EOL
%%
program:
variable_definitions function_definitions {
}
;
function_definitions:
function_head block {} |
function_definitions function_head block
;
identifier_list:
ID |
ID LBRACKET INT_LITERAL RBRACKET |
identifier_list COMMA ID |
identifier_list COMMA ID LBRACKET INT_LITERAL RBRACKET
;
variable_definitions:
| variable_definitions type identifier_list
;
type:
INT |
FLOAT
;
function_head:
type ID arguments
;
arguments:
LPAREN parameter_list RPAREN
;
parameter_list:
| parameters
;
parameters:
type ID |
type ID LBRACKET RBRACKET |
parameters COMMA type ID |
parameters COMMA type ID LBRACKET RBRACKET
;
block:
LBRACE variable_definitions statements RBRACE {}
;
statements:
| statements statement {}
;
statement:
expression SEMI {} |
compound_statement |
RETURN expression SEMI |
IF LPAREN bool_expression RPAREN statement ELSE statement |
WHILE LPAREN bool_expression RPAREN statement |
input_statement SEMI |
output_statement SEMI
;
compound_statement:
LBRACE statements RBRACE {depth1++}
;
expression_list:
| expressions {}
;
expressions:
expression {} |
expressions COMMA expression
;
expression:
variable ASSIGN_OP expression |
variable INC expression |
variable DEC expression |
simple_expression {}
;
variable:
ID |
ID LBRACKET expression RBRACKET
;
input_statement:
CIN |
input_statement STREAMIN variable
;
output_statement:
COUT |
output_statement STREAMOUT expression |
output_statement STREAMOUT STR_LITERAL |
output_statement STREAMOUT ENDL
;
simple_expression:
term {$<s>$ = $<s>1} |
ADD term { $<s>$ = $<s>2} |
SUB term { char* quad_operation;
if(strcmp($<s>2->EntryData->kind,"i")) {
quad_operation = "n";
} else {
quad_operation = "N";
}
setKind($<s>2->EntryData->kind); setStackLocation(stackPointer); struct entry *data = lookUp($<s>2->EntryData->kind);
FILE *quadInsert;
quadInsert = fopen("quads.q", "a");
fprintf(quadInsert, "%s %d /%d", quad_operation,0,stackPointer);
if(strcmp(tempKind,"i")) {
stackPointer = stackPointer-2;
} else {
stackPointer = stackPointer-4;
}
fclose(quadInsert);
$<s>$ = data;
} |
simple_expression ADD term {
char* quad_operation;
FILE *quadAinsert;
quadAinsert = fopen("quads.q", "a");
if(strcmp($<s>3->EntryData->kind,"i")) {
quad_operation = "F";
fprintf(quadAinsert, "%s %d /%d", quad_operation, 0, stackPointer);
setKind("f"); setStackLocation(stackPointer); lookUp("f"); kindOne = "f"; stackPointerOne = stackPointer;
stackPointer = stackPointer-4;
} else {
setKind(tempKind); setStackLocation(stackPointer); lookUp(tempKind);
stackPointerOne = getStackLocation(); stackPointer = stackPointer-4;
}
if(strcmp($<s>1->EntryData->kind,"i")) {
quad_operation = "F";
fprintf(quadAinsert, "%s %d /%d", quad_operation, 0, stackPointer);
setKind("f"); setStackLocation(stackPointer); lookUp("f"); kindTwo = "f"; stackPointerTwo = stackPointer;
stackPointer = stackPointer-4;
} else {
stackPointerTwo = getStackLocation();
}
if (strcmp(kindOne,"f") && strcmp(kindTwo,"f")) {
quad_operation = "A";
fprintf(quadAinsert, "%s /%d /%d /%d", quad_operation, stackPointerOne, stackPointerTwo, stackPointer);
}
fclose(quadAinsert);
setKind("f"); setStackLocation(stackPointer); struct entry *data = lookUp("f");
stackPointer = stackPointer-4;
$<s>$ = data
} |
simple_expression SUB term {
char* quad_operation;
FILE *quadBinsert;
quadBinsert = fopen("quads.q", "a");
if(strcmp($<s>3->EntryData->kind,"i")) {
quad_operation = "F";
fprintf(quadBinsert, "%s %d /%d", quad_operation, 0, stackPointer);
setKind("f"); setStackLocation(stackPointer); data1 = lookUp("f1");
stackPointer = stackPointer-4;
} else {
setKind($<s>3->EntryData->kind); setStackLocation(stackPointer); data1 = lookUp("f1");
stackPointer = stackPointer-4;
}
if(strcmp($<s>1->EntryData->kind,"i")) {
quad_operation = "F";
fprintf(quadBinsert, "%s %d /%d", quad_operation, 0, stackPointer);
setKind("f"); setStackLocation(stackPointer); data2 = lookUp("f2");
stackPointer = stackPointer-4;
} else {
data2 = $<s>1;
}
if (strcmp(data1->EntryData->kind,"f") && strcmp(data2->EntryData->kind,"f")) {
quad_operation = "S";
fprintf(quadBinsert, "%s /%d /%d /%d", quad_operation, stackPointerOne, stackPointerTwo, stackPointer);
}
fclose(quadBinsert);
setKind("f"); setStackLocation(stackPointer); struct entry *data = lookUp("f1");
stackPointer = stackPointer-4;
$<s>$ = data
}
;
term:
factor {$<s>$ = $<s>1} |
term MUL factor {
char* quad_operation;
FILE *quadMinsert;
quadMinsert = fopen("quads.q", "a");
if(strcmp($<s>3->EntryData->kind,"i")) {
quad_operation = "F";
fprintf(quadMinsert, "%s %d /%d", quad_operation, 0, stackPointer);
setKind("f"); setStackLocation(stackPointer); lookUp("f"); kindOne = "f"; stackPointerOne = stackPointer;
stackPointer = stackPointer-4;
} else {
setKind(tempKind); setStackLocation(stackPointer); lookUp(tempKind);
stackPointerOne = getStackLocation(); stackPointer = stackPointer-4;
}
if(strcmp($<s>1->EntryData->kind,"i")) {
quad_operation = "F";
fprintf(quadMinsert, "%s %d /%d", quad_operation, 0, stackPointer);
setKind("f"); setStackLocation(stackPointer); lookUp("f"); kindTwo = "f"; stackPointerTwo = stackPointer;
stackPointer = stackPointer-4;
} else {
stackPointerTwo = getStackLocation();
}
if (strcmp(kindOne,"f") && strcmp(kindTwo,"f")) {
quad_operation = "M";
fprintf(quadMinsert, "%s /%d /%d /%d", quad_operation, stackPointerOne, stackPointerTwo, stackPointer);
}
fclose(quadMinsert);
setKind("f"); setStackLocation(stackPointer); struct entry *data = lookUp("f");
stackPointer = stackPointer-4;
$<s>$ = data;
} |
term DIV factor {char* quad_operation;
FILE *quadMinsert;
quadMinsert = fopen("quads.q", "a");
if(strcmp($<s>3->EntryData->kind,"i")) {
quad_operation = "F";
fprintf(quadMinsert, "%s %d /%d", quad_operation, 0, stackPointer);
setKind("f"); setStackLocation(stackPointer); lookUp("f"); kindOne = "f"; stackPointerOne = stackPointer;
stackPointer = stackPointer-4;
} else {
setKind(tempKind); setStackLocation(stackPointer); lookUp(tempKind);
stackPointerOne = getStackLocation(); stackPointer = stackPointer-4;
}
if(strcmp($<s>1->EntryData->kind,"i")) {
quad_operation = "F";
fprintf(quadMinsert, "%s %d /%d", quad_operation, 0, stackPointer);
setKind("f"); setStackLocation(stackPointer); lookUp("f"); kindTwo = "f"; stackPointerTwo = stackPointer;
stackPointer = stackPointer-4;
} else {
stackPointerTwo = getStackLocation();
}
if (strcmp(kindOne,"f") && strcmp(kindTwo,"f")) {
quad_operation = "D";
fprintf(quadMinsert, "%s /%d /%d /%d", quad_operation, stackPointerOne, stackPointerTwo, stackPointer);
}
fclose(quadMinsert);
setKind("f"); setStackLocation(stackPointer); struct entry *data = lookUp("f");
stackPointer = stackPointer-4;
$<s>$ = data
} |
term MOD factor {char* quad_operation;
FILE *quadMinsert;
quadMinsert = fopen("quads.q", "a");
if(strcmp($<s>3->EntryData->kind,"i")) {
quad_operation = "F";
fprintf(quadMinsert, "%s %d /%d", quad_operation, 0, stackPointer);
setKind("f"); setStackLocation(stackPointer); lookUp("f"); kindOne = "f"; stackPointerOne = stackPointer;
stackPointer = stackPointer-4;
} else {
setKind(tempKind); setStackLocation(stackPointer); lookUp(tempKind);
stackPointerOne = getStackLocation(); stackPointer = stackPointer-4;
}
if(strcmp($<s>1->EntryData->kind,"i")) {
quad_operation = "F";
fprintf(quadMinsert, "%s %d /%d", quad_operation, 0, stackPointer);
setKind("f"); setStackLocation(stackPointer); lookUp("f"); kindTwo = "f"; stackPointerTwo = stackPointer;
stackPointer = stackPointer-4;
} else {
stackPointerTwo = getStackLocation();
}
if (strcmp(kindOne,"f") && strcmp(kindTwo,"f")) {
quad_operation = "r";
fprintf(quadMinsert, "%s /%d /%d /%d", quad_operation, stackPointerOne, stackPointerTwo, stackPointer);
}
fclose(quadMinsert);
setKind("f"); setStackLocation(stackPointer); struct entry *data = lookUp("f");
stackPointer = stackPointer-4;
$<s>$ = data;
}
;
factor:
ID |
ID LPAREN expression_list RPAREN {
} |
literal {$<s>$ = $<s>1} |
LPAREN expression RPAREN |
ID LBRACKET expression RBRACKET
;
literal:
INT_LITERAL { tempKind = "i"; setKind(tempKind); struct entry *data = lookUp("i"); $<s>$ = data;
} |
FLT_LITERAL { tempKind = "f"; setKind(tempKind); struct entry *data = lookUp("f"); $<s>$ = data;
}
;
bool_expression:
bool_term |
bool_expression OR bool_term
;
bool_term:
bool_factor |
bool_term AND bool_factor
;
bool_factor:
NOT bool_factor |
LPAREN bool_expression RPAREN |
simple_expression LT simple_expression |
simple_expression GT simple_expression |
simple_expression LTE simple_expression |
simple_expression GTE simple_expression |
simple_expression EQUAL simple_expression |
simple_expression NOT_EQUAL simple_expression
;
%%
void yyerror(char *s)
{
fprintf(stderr, "error: %s\n", s);
}
Lexer.l (Flex)
%{
#include "parser.tab.h"
int ldepth = 0;
%}
%option yylineno
%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"%" { return MOD; }
"<" { return LT; }
">" { return GT; }
"<=" { return LTE; }
">=" { return GTE; }
"==" { return EQUAL; }
"!=" { return NOT_EQUAL; }
"&&" { return AND; }
"||" { return OR; }
"+=" { return INC; }
"-=" { return DEC; }
"=" { return ASSIGN_OP; }
">>" { return STREAMIN; }
"<<" { return STREAMOUT; }
";" { return SEMI; }
"," { return COMMA; }
"(" { return LPAREN; }
")" { return RPAREN; }
"[" { return LBRACKET; }
"]" { return RBRACKET; }
"{" { ldepth++; return LBRACE; }
"}" { ldepth--; return RBRACE; }
"!" { return NOT; }
"cin" { return CIN; }
"cout" { return COUT; }
"if" { return IF; }
"else" { return ELSE; }
"int" { return INT; }
"float" { return FLOAT; }
"while" { return WHILE; }
"return" { return RETURN; }
"endl" { return EOL; }
[A-Za-z_]+ { return ID; }
"\"".*"\"" { return STR_LITERAL; }
[0-9]+ { return INT_LITERAL; }
[0-9]*(\.[0-9]+)?([eE][-+]?[0-9]+)? { return FLT_LITERAL; }
\n { return EOL; }
[ \t] { /*ignore whitespace*/ }
\"[^\"\n]*$ { printf("Unterminated string at line %d\n", yylineno); }
\([^)\n]*$ { printf("Unmatched ( at line %d\n", yylineno); }
\[[^]\n]*$ { printf("Unmatched [ at line %d\n", yylineno); }
\{[^}\n]*$ { printf("Unmatched { at line %d\n", yylineno); }
"cin >"[^>] { printf("Missing > at line %d\n", yylineno); }
"cout <"[^<] { printf("Missing < at line %d\n", yylineno); }
"//".* { /* comment */ }
"#".* { /* comment */ }
"/*".*"*/" { /*block comment */ }
. { printf("Mystery character %c at line %d\n", *yytext, yylineno); }
%%
Driver.cpp
#include <string>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdio.h>
using namespace std;
/*
Perform error checking on each line as it is read from the file. Checking for sntax error, missing semicolons,
and anything else we can think of that would be very bad to happen.
*/
/*extern "C"
{
int yyparse();
#include "parser.tab.h"
}*/
ofstream variable_file;
ifstream variables;
void errors(string line, int line_counter)
{
size_t tab = line.rfind("\t");
size_t check1 = line.find("if");
size_t check2 = line.find("while");
size_t check3 = line.find("else");
size_t check4 = line.find("{");
size_t check5 = line.find("}");
size_t typeI = line.find("int");
size_t typeF = line.find("float");
size_t Lparen = line.find("(");
size_t Rparen = line.find(")");
//check for a ;
if( int(check1) >= 0 && int(check1) < 2 ) //no ; needed, check relops
{
//check to see if "if" is in a string, if n ot then ignore
//compare find val of " and find val of if
//find(") < "if" < rfind(")
}
else if( int(check2) >= 0 && int(check2) < 5 ) //ignore while started statements
{
}
else if( int(check3) >= 0 && int(check3) < 4 ) //ignore else started statements
;
else if( int(check4) >= 0 )
;
else if( int(check5) >= 0 )
;
else if( line.empty() == 1 )
;
else if( typeI != string::npos | typeF != string::npos | Lparen != string::npos | Rparen != string::npos )
;
else //else check for missing ;
{
if( line.rfind(";") == string::npos )
cout << "Error: Missing ; on line " << line_counter-1 << endl;
}
//check types
}
string strip_tabs(string line)
{
string tabless_line;
size_t position = line.rfind("\t");
if( position != string::npos )
tabless_line = line.substr( int(position) );
return tabless_line;
}
/*
Function to determine if we want to perform error checking on the string or not
*/
int check_string(string line)
{
const char* my_line;
bool multiline_comment = 0;
string multiline = "*/";
my_line = line.c_str();
size_t found = line.find(multiline);
//skip multiline comments in progress
if( multiline_comment )
return 1;
//skip beginning of multi line comments
if(my_line[0] == '/' && my_line[1] == '*')
{
multiline_comment = 1;
return 1;
}
//skip end of multiline comments
if( multiline_comment && found != string::npos )
{
multiline_comment = 0; //end of comment, reset flag
return 1;
}
//empty line, no error checking needed
if( line.empty() == true )
return 1;
//empty except for tabs
if( line == "\t" )
return 1;
//skip newlines, # statements. & comments
if( my_line[0] == '#' | ( my_line[0] == '/' && my_line[1] == '/' | my_line[0] == '\n') )
return 1; //no error checking
return 0; //error checking needed
}
void find_variables(string line)
{
const char* new_line = line.c_str();
string new_string;
int x = 0;
int semi_position;
// int x = 0
// x = 1 + 2 +...
bool float_flag = false;
string output = "";
string output1 = "int ";
string output2 = "float ";
string::iterator it;
int str_len = line.length();
if( line.find("=", 0) != string::npos)
{
int x = 0;
for(it = line.begin(); it < line.end(); it++)
{
string s (line.begin()+x, line.end()-(str_len+x) );
if( s.compare("1") | s.compare("2") | s.compare("3") | s.compare("4") | s.compare("5") | s.compare("6") | s.compare("7") | s.compare("8") | s.compare("9") | s.compare("0") )
{
string t (line.begin()+x+1, line.end()-str_len+x);
if(t.compare(" ") | t.compare(";"))
{
output += t;
if( float_flag)
variable_file << output << "f\n";
else
variable_file << output << "\n";
}
if(t.compare(".") != string::npos)
float_flag = true;
else
output += t;
}
}
/*
while (new_line[x] != '\0' )
{
//int case
if(new_line[x] == 'i')
if(new_line[x+1] == 'n')
if(new_line[x+2] == 't')
if(new_line[x+3] == ' ')
{
semi_position = line.find(";", x+3);
new_string = line.substr( x+4, (semi_position - 4) );
output1 += new_string;
output1 += '\n';
variable_file << output1;
}
//make literal case 1,2...
//float case
if(new_line[x] == 'f')
if(new_line[x+1] == 'l')
if(new_line[x+2] == 'o')
if(new_line[x+3] == 'a')
if(new_line[x+4] == 't')
if(new_line[x+5] == ' ')
{
semi_position = line.find(";", x+5);
new_string = line.substr( x+4, (semi_position - 6) );
output2 += new_string;
output2 += '\n';
variable_file << output2;
}
x++;
}*/
}
}
void write_globals()
{
FILE *quadFile;
quadFile = fopen("quads.q", "a");
int globalCurVal = 0, globalMaxVal = 0;
string line;
variables.open("variables.txt");
string::iterator it;
int str_length;
int val1;
float val2;
while( !variables.eof() )
{
getline(variables, line);
str_length = line.length();
if(line.find("f") == string::npos) //not float
{
string temp = line.substr(0, str_length -1);
val2 = atof(temp.c_str() );
fprintf(quadFile, "%d", globalCurVal);
fprintf(quadFile, " %d\n", val2);
globalCurVal = globalCurVal + 4;
globalMaxVal = globalCurVal;
}
else
{
val1 = atoi(line.c_str() );
fprintf(quadFile, " %d\n", globalCurVal);
fprintf(quadFile, " %f\n", val1);
globalCurVal = globalCurVal + 2;
globalMaxVal = globalCurVal;
}
/*
str_length = line.length();
int int_length = str_length - 3;
int float_length = str_length - 5;
string temp1 ( line.begin(), line.end()-int_length ); //int case
string temp2 ( line.begin(), line.end()-float_length ); //float case
if(temp1.compare("int") == 0)
if(temp2.compare("float") == 0)
{
}
*/
}
fprintf(quadFile, "%s %d %d\n","$",1,globalMaxVal);
fprintf(quadFile, "%s %d\n","#",globalMaxVal*2);
fclose(quadFile);
}
int main(int argc, char **argv)
{
string filename;
cout <<"Enter a file to compile:"<<endl;
cin >>filename;
cout << "You entered... " << filename << endl;
//open the file for reading.
string line;
ifstream myfile (filename.c_str());
variable_file.open("variables.txt");
int line_counter = 1;
if ( myfile.is_open() )
{
while (! myfile.eof() )
{
cout << line_counter++ << "\t";
getline (myfile,line);
cout << line;
//scan each line for variables
// find_variables(line);
//check for errors here!!!!
if( check_string(line) == 0)
errors( /*strip_tabs*/line, line_counter);
cout << endl;
}
}
variable_file.close();
write_globals();
//yyparse();
myfile.close();
}
Makefile
compiler: Sym_Table.c fb
g++ -o compiler fb Sym_Table.c
fb: driver.cpp parser.tab.c lex.yy.c
g++ driver.cpp parser.tab.c lex.yy.c -lfl
parser.tab.c: parser.y
bison -d parser.y
lex.yy.c: lexer.l
flex lexer.l
Sym_Table.o: Sym_Table.c
gcc -c Sym_Table.c
So are we fucking up the makefile? Is there something wrong with the parser file to cause this? Aaaaahhh, help!
Posts
Also, just doing an extern with the function declaration in the first section of lexer.l could be an alternate fix, but I'm not sure if that was allowed.
My Machines & Languages course was years ago, so take all that with a grain of salt and let us know. Finally, remember to do a make clean directive;oP
Now I'm getting this linker error:
ld: duplicate symbol yy_flush_buffer(yy_buffer_state*) in /var/tmp//cc1baWiV.o and /var/tmp//cclqcIz5.o
will investigate more when I get out of class
See how many books I've read so far in 2010
See how many books I've read so far in 2010
See how many books I've read so far in 2010
I don't think so, I believe it should again be in parser.y(as you never explicitly call yylex, right?).
Quick google for yylex + extern C:
http://meditation-art.blogspot.com/2008/01/lex-yacc-with-c-types-of-external.html
That should explain it.
The problem was we had #include "Sym_Table.c" in the parser, and were compiling it and linking it with everything else in the make file, hence duplicate symbols.
So much pain...
See how many books I've read so far in 2010