This is mildly aggravating, but my flex and bison generated files won't compile under Visual Studio C++ 2008. It has to do with some of the structures (yyval for starters) and some apparently loose characters in the files. I'll post the compiler output, but this is my third day of working on this and I am stumped.
------ Build started: Project: ASL, Configuration: Debug Win32 ------
Compiling...
language.lex.c
.\language.l(50) : error C2065: 'yyval' : undeclared identifier
.\language.l(50) : error C2224: left of '.numconst' must have struct/union type
.\language.l(50) : warning C4013: 'atoi' undefined; assuming extern returning int
.\language.l(51) : error C2065: 'yyval' : undeclared identifier
.\language.l(51) : error C2224: left of '.floatconst' must have struct/union type
.\language.l(51) : warning C4013: 'atof' undefined; assuming extern returning int
.\language.l(52) : error C2065: 'yyval' : undeclared identifier
.\language.l(52) : error C2224: left of '.boolconst' must have struct/union type
.\language.l(53) : error C2065: 'yyval' : undeclared identifier
.\language.l(53) : error C2224: left of '.boolconst' must have struct/union type
.\language.l(55) : error C2065: 'yyval' : undeclared identifier
.\language.l(55) : error C2224: left of '.identifier' must have struct/union type
language.lex.c(1724) : warning C4013: 'exit' undefined; assuming extern returning int
language.lex.c(1787) : warning C4013: 'malloc' undefined; assuming extern returning int
language.lex.c(1805) : warning C4013: 'realloc' undefined; assuming extern returning int
language.lex.c(1815) : warning C4013: 'free' undefined; assuming extern returning int
language.tab.c
language.tab.c(1094) : error C2449: found '{' at file scope (missing function header?)
language.tab.c(1962) : error C2059: syntax error : '}'
Generating Code...
Build log was saved at "file://c:\Documents and Settings\Austen\My Documents\Visual Studio 2008\Projects\ASL\ASL\Debug\BuildLog.htm"
ASL - 12 error(s), 6 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
language.y
/*
* yacc grammar
*/
%{
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "error.h"
#include "nodetree.h"
int yylex();
extern SCRIPT *sc;
%}
%start script
%union {
struct SCRIPT *script;
struct ITEM *item;
struct FUNCTION *function;
struct MAIN *main;
struct TYPE *type;
struct IDENTIFIER *identifiers;
struct EXP *exp;
struct DECL *decl;
struct STM *stm;
struct LVALUE *lvalue;
char *identifier;
int numconst;
int boolconst;
float deciconst;
char *stringconst;
};
%token tMAIN tFUNCTION
%token <identifier> tIDENTIFIER
%token <numconst> tNUMCONST
%token <deciconst> tFLOATCONST
%token <boolconst> tBOOLCONST
%token <stringconst> tSTRINGCONST
%token tFLOAT tNUM tBOOL tSTRING
%token tIF tELSE tWHILE tBREAK tCONTINUE tRETURN tPRINT
%token tENDLINE '[' ']' '(' ')' tSCOPE tENDSCOPE
%token '+' '-'
%token '*' '/' '%'
%token '='
%token GE LE EQ NE
%token '^'
%token tAND tOR '!' tNEG
%token ','
%type <script> script
%type <item> ne items neitems
%type <fuction> function
%type <main> main
%type <type> type
%type <identifiers> identifiers
%type <exp> initialization exp unary unarypostfix exps nexps
%type <decl> decl arg args neargs
%type <stm> nestm stm compstm
%type <lvalue> lvalue
/*
* precedence
*/
%left ')'
%left tELSE
%right '='
%left tOR
%left tAND
%left EQ NE
%left '<' '>' GE LE
%left '+' '-'
%left '*' '/' '%'
%left '^'
%%
script : /* empty */
{$$ = NULL;}
| ne
{$$ = $1;}
;
ne : main items
{$$ = $1; $$->next = $2;}
;
items : /* empty */
{$$ = NULL;}
| neitems
{$$ = $1;}
;
neitems: function
{$$ = $1;}
| function neitems
{$$ = $1; $$->next =$2;}
;
type : tNUM
{$$ = makeTYPEnum();}
| tFLOAT
{$$ = makeTYPEfloat();}
| tSTRING
{$$ = makeTYPEstring();}
| tBOOL
{$$ = makeTYPEbool();}
;
decl : type identifiers initialization tENDLINE
{$$ = makeDECLvar($1, $2, $2);}
;
identifiers : tIDENTIFIER
{$$ = makeIDENTIFIER($1);}
| tIDENTIFIER ',' identifiers
{$$ = makeIDENTIFIER($1); $$->next = $3;}
;
initialization : /* empty */
{$$ = NULL;}
| '=' exp
{$$ = $2;}
;
main : tMAIN compstm
{$$ = makeMAIN($2);}
;
function : tFUNCTION tIDENTIFIER '[' args ']' compstm
{$$ = makeFUNCTION($2, $4, $6);}
;
args : /* empty */
{$$ = NULL;}
| neargs
{$$ = $1;}
;
neargs : arg
{$$ = $1;}
| arg ',' neargs
{$$ = $1; $$->next = $3;}
;
arg : type tIDENTIFIER
{$$ = makeDECLarg($1, $2);}
;
compstm : tSCOPE tENDSCOPE
{ $$ = NULL;}
| tSCOPE nestm tENDSCOPE
{$$ = $2;}
;
nestm : stm
{$$ = $1;}
| stm nestm
{$$ = $1; $$->next = $2;}
;
stm : tENDLINE
{$$ = makeSTMskip();}
| tRETURN tENDLINE
{$$ = makeSTMreturn(NULL);}
| tRETURN exp tENDLINE
{$$ = makeSTMreturn($2);}
| tIF '(' exp ')' stm
{$$ = makeSTMif($3, $5); }
| tIF '(' exp ')' stm tELSE stm
{$$ = makeSTMifelse($3, $5, $7); }
| tWHILE '(' exp ')' stm
{$$ = makeSTMwhile($3, $5); }
| tBREAK tENDLINE
{$$ = makeSTMbreak(); }
| tCONTINUE tENDLINE
{$$ = makeSTMcontinue(); }
| compstm
{$$ = makeSTMscope($1);}
| decl
{ $$ = makeSTMdecl($1);}
| exp
{ $$ = makeSTMexp($1);}
| tPRINT '(' exp ')'
{ $$ = makeSTMprint($3);}
;
exp : lvalue '=' exp
{ $$ = makeEXPassignment($1, $3);}
| exp EQ exp
{ $$ = makeEXPequals($1, $3); }
| exp NE exp
{ $$ = makeEXPnequals($1, $3);}
| exp '<' exp
{ $$ = makeEXPless($1, $3); }
| exp '>' exp
{ $$ = makeEXPgreater($1, $3); }
| exp GE exp
{ $$ = makeEXPgequals($1, $3); }
| exp LE exp
{ $$ = makeEXPlequals($1, $3); }
| exp '+' exp
{ $$ = makeEXPplus($1, $3);}
| exp '-' exp
{ $$ = makeEXPminus($1, $3);}
| exp '*' exp
{ $$ = makeEXPmult($1, $3);}
| exp '/' exp
{ $$ = makeEXPdiv($1, $3);}
| exp '%' exp
{$$ = makeEXPmodulo($1, $3);}
| exp '^' exp
{$$ = makeEXPpow($1, $3);}
| exp tOR exp
{$$ = makeEXPor($1, $3);}
| exp tAND exp
{$$ = makeEXPand($1, $3);}
| unary
{$$ = $1;}
;
unary : tNEG unary
{$$ = makeEXPneg($2);}
| '!' unary
{ $$ = makeEXPnot($2);}
| '(' type ')' unary
{ $$ = makeEXPcast($2, $4);}
| unarypostfix
{ $$ = $1;}
;
unarypostfix : tNUMCONST
{$$ = makeEXPnumconst($1);}
| tBOOLCONST
{$$ = makeEXPboolconst($1);}
| tFLOATCONST
{$$ = makeEXPfloatconst($1);}
| tSTRINGCONST
{$$ = makeEXPstringconst($1);}
| lvalue
{$$ = makeEXPlvalue($1);}
| '(' exp ')'
{$$ = $2;}
| tIDENTIFIER '[' exps ']' /* Invoke */
{$$ = makeEXPcall($1, $3); }
;
exps : /* empty */
{$$ = NULL;}
| nexps
{$$ = $1;}
;
nexps : exp
{$$ = NULL;}
| exp ',' nexps
{$$ = $1, $$->next = $3;}
;
lvalue : tIDENTIFIER
{$$ = makeLVALUEid($1);}
;
language.l
%{
#include "language.tab.h"
#include <string.h>
#include "memory.h"
#include "error.h"
extern int lineno;
%}
%%
/* Initial condition */
[ \t]+ ;
\n lineno++;
"//"[^\n]* /*Ignore a line */ ;
bool return tBOOL;
num return tNUM;
decimal return tFLOAT;
# return tNUM;
string return tSTRING;
"$" return tSTRING;
else return tELSE;
if return tIF;
main return tMAIN;
function return tFUNCTION;
while return tWHILE;
break return tBREAK;
continue return tCONTINUE;
return return tRETURN;
print return tPRINT;
";" return tENDLINE;
"[" return '[';
"]" return ']';
"(" return '(';
")" return ')';
SECTION return tSCOPE;
ENDSECTION return tENDSCOPE;
"+" return '+';
"-" return '-';
NEG return tNEG;
"*" return '*';
"/" return '/';
AND return tAND;
OR return tOR;
"!" return '!';
"=" return '=';
"==" return EQ;
">=" return GE;
"<=" return LE;
"!=" return NE;
"^" return '^';
0|([1-9][0-9]*) { yyval.numconst = atoi(yytext); return tNUMCONST;}
0"."0|([1-9][0-9]*"."[0-9][0-9]*) {yyval.floatconst = atof(yytext); return tFLOATCONST;}
TRUE {yyval.boolconst = 1; return tBOOLCONST;}
FALSE {yyval.boolconst = 0; return tBOOLCONST;}
\"[^\"\n]*\" { yytext[strlen(yytext)-1]='\0';yylval.stringconst = strdup(yytext+1);return tSTRINGCONST; }
[A-Za-z_][A-za-z0-9]* { yyval.identifier = strdup(yytext); return tIDENTIFIER;}
. yyerror("Unknown characters '%s'.", yytext);
%%
I'm kinda at the end of my rope on this one, I don't understand why a tool is generating faulty code (and I assume it's user error, but I can't find any mistakes).