blob: a00279c31af34d33ddf76bbc2a34c3ff5e4d1d46 [file] [log] [blame]
%{
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "tools/re2c/globals.h"
#include "tools/re2c/parse.h"
int yylex(void);
void yyerror(const char*);
static unsigned int accept;
static RegExp *spec;
static Scanner *in;
%}
%start spec
%union {
Symbol *symbol;
RegExp *regexp;
Token *token;
char op;
ExtOp extop;
}
%token CLOSESIZE CLOSE ID CODE RANGE STRING
%type <op> CLOSE
%type <op> close
%type <extop> CLOSESIZE
%type <symbol> ID
%type <token> CODE
%type <regexp> RANGE STRING
%type <regexp> rule look expr diff term factor primary
%%
spec :
{ accept = 0;
spec = NULL; }
| spec rule
{ spec = spec? mkAlt(spec, $2) : $2; }
| spec decl
;
decl : ID '=' expr ';'
{ if($1->re)
Scanner_fatal(in, "sym already defined");
$1->re = $3; }
;
rule : expr look CODE
{ $$ = RegExp_new_RuleOp($1, $2, $3, accept++); }
;
look :
{ $$ = RegExp_new_NullOp(); }
| '/' expr
{ $$ = $2; }
;
expr : diff
{ $$ = $1; }
| expr '|' diff
{ $$ = mkAlt($1, $3); }
;
diff : term
{ $$ = $1; }
| diff '\\' term
{ $$ = mkDiff($1, $3);
if(!$$)
Scanner_fatal(in, "can only difference char sets");
}
;
term : factor
{ $$ = $1; }
| term factor
{ $$ = RegExp_new_CatOp($1, $2); }
;
factor : primary
{ $$ = $1; }
| primary close
{
switch($2){
case '*':
$$ = mkAlt(RegExp_new_CloseOp($1), RegExp_new_NullOp());
break;
case '+':
$$ = RegExp_new_CloseOp($1);
break;
case '?':
$$ = mkAlt($1, RegExp_new_NullOp());
break;
}
}
| primary CLOSESIZE
{
$$ = RegExp_new_CloseVOp($1, $2.minsize, $2.maxsize);
}
;
close : CLOSE
{ $$ = $1; }
| close CLOSE
{ $$ = ($1 == $2) ? $1 : '*'; }
;
primary : ID
{ if(!$1->re)
Scanner_fatal(in, "can't find symbol");
$$ = $1->re; }
| RANGE
{ $$ = $1; }
| STRING
{ $$ = $1; }
| '(' expr ')'
{ $$ = $2; }
;
%%
void yyerror(const char* s){
Scanner_fatal(in, s);
}
int yylex(){
return Scanner_scan(in);
}
void line_source(FILE *o, unsigned int line)
{
char * fnamebuf;
char * token;
if (iFlag)
return;
fprintf(o, "#line %u \"", line);
if( fileName != NULL ) {
fnamebuf = mystrdup( fileName );
} else {
fnamebuf = mystrdup( "<stdin>" );
}
token = strtok( fnamebuf, "\\" );
for(;;) {
fprintf(o, "%s", token);
token = strtok( NULL, "\\" );
if( token == NULL ) break;
fputs("\\\\", o);
}
fputs("\"\n", o); oline++;
free( fnamebuf );
}
void parse(FILE *i, FILE *o){
time_t now;
time(&now);
fputs("/* Generated by re2c 0.9.1-C on ", o);
fprintf(o, "%-24s", ctime(&now));
fputs(" */\n", o); oline+=2;
in = Scanner_new(i);
line_source(o, Scanner_line(in));
while(Scanner_echo(in, o)){
yyparse();
if(spec)
genCode(o, spec);
line_source(o, Scanner_line(in));
}
}