%{
#include "regex.h"
#include <iostream>
#include <map>
using namespace std;
extern int yylex();

#define YYDEBUG 1

void yyerror(char* str)
{
	cerr<<str<<endl;
}

map<string, Regex*> defs;

%}

%union
{
	char  char_attr;
	char* str_attr;
	Regex* regex_attr;
};

%type<regex_attr> regex regexdisj regexconcat
%token<str_attr>  ID CHARCLASS
%token<char_attr> CHAR
%token PRINT BASIC

%%
dat : dat stmt ';'
	|
	;

stmt : ID '=' regex  
	{ 
		map<string, Regex*>::iterator i = defs.find($1);
		if (i == defs.end())
		     defs[$1] = $3; 
		else
		{
			delete i->second;
			i->second = $3;
		}
		free($1); 
	}
	| PRINT '(' regex ')' {$3->Print(cout); cout<<endl;}
	;

regex : regex '|' regexdisj { $$ = new RegexDisj($1, $3); }
	| regexdisj { $$ = $1; }
	| BASIC '(' regex ')' { $$ = $3->basic(); delete $3; }
	;

regexdisj : regexdisj regexconcat { $$ = new RegexConcat($1, $2); }
	| regexconcat { $$ = $1; }
	;

regexconcat : regexconcat '?' {$$ = new RegexQM($1);}
	| regexconcat '+' { $$ = new RegexPLUS($1); }
	| regexconcat '*' { $$ = new RegexTIMES($1); }
	| CHAR 	          { $$ = new RegexChar($1); }
	| CHARCLASS     { $$ = new RegexCharClass($1[1], $1[3]); free($1);}
	| ID { map<string, Regex*>::iterator i = defs.find($1);
	       if (i == defs.end())
	       {
			yyerror("Unknown def");
			exit(1);
	       }
	       $$ = i->second->Clone();
               free($1);
	     } 
	| '(' regex ')' { $$ = $2; }
	; 

%%

main()
{
	yydebug = 0;
	yyparse();
}
