The new forums will be named Coin Return (based on the most recent vote)! You can check on the status and timeline of the transition to the new forums here.
The Guiding Principles and New Rules document is now in effect.

Need help makeing a compiler [Flex & Bison]

clsCorwinclsCorwin Registered User regular
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!

clsCorwin on

Posts

  • zeenyzeeny Registered User regular
    edited December 2009
    Off the top of my head, declaring "void yyerror(char *s);" in the first section(or moving the whole function there) of parser.y should do it. I'm pretty sure specific functions have to be declared there by convention, but I don't have the tools to test right now.
    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

    zeeny on
  • clsCorwinclsCorwin Registered User regular
    edited December 2009
    Ok, declaring void yyerror(char *s); was money.

    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

    clsCorwin on
  • clsCorwinclsCorwin Registered User regular
    edited December 2009
    ok, so the #include "lex.yy.c" in the parser.y file is causing this, but ithout that I get a yylrx undefined in scope error

    clsCorwin on
  • zeenyzeeny Registered User regular
    edited December 2009
    I assume that was a typo and you meant yylex? Well, again, I'm not sure, but I believe the problem comes from you using CPP & C at the same time. Try and declare your yylex as EXTERN "C" in the first block with the exact definition.(it should be something like "EXTERN "C" int yylex(void);". I think there was a flex option that does all that work for you, but I don't remember what it it was.

    zeeny on
  • clsCorwinclsCorwin Registered User regular
    edited December 2009
    Where should I put that extern? In the driver along with the extern for yyparse()?

    clsCorwin on
  • zeenyzeeny Registered User regular
    edited December 2009
    clsCorwin wrote: »
    Where should I put that extern? In the driver along with the extern for yyparse()?

    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.

    zeeny on
  • clsCorwinclsCorwin Registered User regular
    edited December 2009
    So, that wasn't the problem. We did need to #include "lex.yy.c" so we didn't need to do anymore externs.

    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...

    clsCorwin on
Sign In or Register to comment.