mirror of https://github.com/yasm/yasm.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
3.0 KiB
189 lines
3.0 KiB
%{ |
|
#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 char *mystrdup(const char *str); |
|
|
|
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); |
|
} |
|
|
|
static char * |
|
mystrdup(const char *str) |
|
{ |
|
size_t len; |
|
char *copy; |
|
|
|
len = strlen(str) + 1; |
|
copy = malloc(len); |
|
memcpy(copy, str, len); |
|
return (copy); |
|
} |
|
|
|
void line_source(FILE *o, unsigned int line) |
|
{ |
|
char * fnamebuf; |
|
char * token; |
|
|
|
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)); |
|
} |
|
}
|
|
|