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.
249 lines
4.7 KiB
249 lines
4.7 KiB
#include <time.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <stdlib.h> |
|
#include "tools/re2c/globals.h" |
|
#include "tools/re2c/parse.h" |
|
#include "tools/re2c/parser.h" |
|
|
|
int yylex(void); |
|
static RegExp *parse_expr(void); |
|
static RegExp *parse_diff(void); |
|
static RegExp *parse_term(void); |
|
static RegExp *parse_factor(void); |
|
static RegExp *parse_primary(void); |
|
|
|
static unsigned int accept; |
|
static RegExp *spec; |
|
static Scanner *in; |
|
|
|
static int curtok, peektok; |
|
yystype yylval; |
|
static yystype peekval; |
|
|
|
#define get_next_token() (curtok = yylex()) |
|
|
|
static void |
|
get_peek_token(void) |
|
{ |
|
yystype temp = yylval; /* structure copy */ |
|
if (peektok != NONE) |
|
Scanner_fatal(in, "more than one token of lookahead?"); |
|
peektok = yylex(); |
|
peekval = yylval; /* structure copy */ |
|
yylval = temp; |
|
} |
|
|
|
static void |
|
yyparse(void) |
|
{ |
|
RegExp *re, *look; |
|
|
|
accept = 0; |
|
spec = NULL; |
|
get_next_token(); |
|
while (curtok != 0) { |
|
switch (curtok) { |
|
case ID: |
|
get_peek_token(); |
|
if (peektok == '=') { |
|
/* ID = expr; */ |
|
Symbol *sym = yylval.symbol; |
|
get_next_token(); /* id */ |
|
get_next_token(); /* = */ |
|
re = parse_expr(); |
|
if (curtok != ';') |
|
Scanner_fatal(in, "missing `;' after regexp"); |
|
get_next_token(); /* ; */ |
|
if (sym->re) |
|
Scanner_fatal(in, "sym already defined"); |
|
sym->re = re; |
|
break; |
|
} |
|
/*@fallthrough@*/ |
|
default: |
|
/* rule: expr [/ expr] CODE */ |
|
re = parse_expr(); |
|
if (!re) |
|
Scanner_fatal(in, "expression syntax error"); |
|
|
|
if (curtok == '/') { |
|
get_next_token(); /* / */ |
|
look = parse_expr(); |
|
} else |
|
look = RegExp_new_NullOp(); |
|
|
|
if (curtok != CODE) |
|
Scanner_fatal(in, "missing code after regexp"); |
|
re = RegExp_new_RuleOp(re, look, yylval.token, accept++); |
|
get_next_token(); /* CODE */ |
|
spec = spec ? mkAlt(spec, re) : re; |
|
} |
|
} |
|
} |
|
|
|
static RegExp * |
|
parse_expr(void) |
|
{ |
|
RegExp *e, *f; |
|
e = parse_diff(); |
|
while (curtok == '|') { |
|
get_next_token(); /* | */ |
|
f = parse_diff(); |
|
e = mkAlt(e, f); |
|
} |
|
return e; |
|
} |
|
|
|
static RegExp * |
|
parse_diff(void) |
|
{ |
|
RegExp *e, *f; |
|
e = parse_term(); |
|
while (curtok == '\\') { |
|
get_next_token(); /* \ */ |
|
f = parse_term(); |
|
e = mkDiff(e, f); |
|
if(!e) |
|
Scanner_fatal(in, "can only difference char sets"); |
|
} |
|
return e; |
|
} |
|
|
|
static RegExp * |
|
parse_term(void) |
|
{ |
|
RegExp *e, *f; |
|
e = parse_factor(); |
|
while ((f = parse_factor())) { |
|
e = RegExp_new_CatOp(e, f); |
|
} |
|
return e; |
|
} |
|
|
|
static RegExp * |
|
parse_factor(void) |
|
{ |
|
RegExp *e; |
|
char ch; |
|
e = parse_primary(); |
|
while (curtok == CLOSE || curtok == CLOSESIZE) { |
|
switch (curtok) { |
|
case CLOSE: |
|
ch = yylval.op; |
|
while (get_next_token() == CLOSE) { |
|
if (ch != yylval.op) |
|
ch = '*'; |
|
} |
|
switch (ch) { |
|
case '*': |
|
e = mkAlt(RegExp_new_CloseOp(e), RegExp_new_NullOp()); |
|
break; |
|
case '+': |
|
e = RegExp_new_CloseOp(e); |
|
break; |
|
case '?': |
|
e = mkAlt(e, RegExp_new_NullOp()); |
|
break; |
|
} |
|
break; |
|
case CLOSESIZE: |
|
e = RegExp_new_CloseVOp(e, yylval.extop.minsize, |
|
yylval.extop.maxsize); |
|
get_next_token(); /* CLOSESIZE */ |
|
break; |
|
default: |
|
Scanner_fatal(in, "parse error"); |
|
break; |
|
} |
|
} |
|
return e; |
|
} |
|
|
|
static RegExp * |
|
parse_primary(void) |
|
{ |
|
RegExp *e; |
|
switch (curtok) { |
|
case ID: |
|
if (!yylval.symbol->re) |
|
Scanner_fatal(in, "can't find symbol"); |
|
e = yylval.symbol->re; |
|
get_next_token(); |
|
break; |
|
case RANGE: |
|
case STRING: |
|
e = yylval.regexp; |
|
get_next_token(); |
|
break; |
|
case '(': |
|
get_next_token(); |
|
e = parse_expr(); |
|
if (curtok != ')') |
|
Scanner_fatal(in, "missing closing parenthesis"); |
|
get_next_token(); |
|
break; |
|
default: |
|
return NULL; |
|
} |
|
return e; |
|
} |
|
|
|
int |
|
yylex(void) |
|
{ |
|
if (peektok != NONE) { |
|
int tok = peektok; |
|
yylval = peekval; |
|
peektok = NONE; |
|
return tok; |
|
} |
|
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); |
|
|
|
peektok = NONE; |
|
|
|
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)); |
|
} |
|
}
|
|
|