Home | History | Annotate | Download | only in re2c
      1 #include <time.h>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <stdlib.h>
      5 #include "tools/re2c/globals.h"
      6 #include "tools/re2c/parse.h"
      7 #include "tools/re2c/parser.h"
      8 
      9 int yylex(void);
     10 static RegExp *parse_expr(void);
     11 static RegExp *parse_diff(void);
     12 static RegExp *parse_term(void);
     13 static RegExp *parse_factor(void);
     14 static RegExp *parse_primary(void);
     15 
     16 static unsigned int accept;
     17 static RegExp *spec;
     18 static Scanner *in;
     19 
     20 static int curtok, peektok;
     21 yystype yylval;
     22 static yystype peekval;
     23 
     24 #define get_next_token()    (curtok = yylex())
     25 
     26 static void
     27 get_peek_token(void)
     28 {
     29     yystype temp = yylval; /* structure copy */
     30     if (peektok != NONE)
     31 	Scanner_fatal(in, "more than one token of lookahead?");
     32     peektok = yylex();
     33     peekval = yylval; /* structure copy */
     34     yylval = temp;
     35 }
     36 
     37 static void
     38 yyparse(void)
     39 {
     40     RegExp *re, *look;
     41 
     42     accept = 0;
     43     spec = NULL;
     44     get_next_token();
     45     while (curtok != 0) {
     46 	switch (curtok) {
     47 	    case ID:
     48 		get_peek_token();
     49 		if (peektok == '=') {
     50 		    /* ID = expr; */
     51 		    Symbol *sym = yylval.symbol;
     52 		    get_next_token(); /* id */
     53 		    get_next_token(); /* = */
     54 		    re = parse_expr();
     55 		    if (curtok != ';')
     56 			Scanner_fatal(in, "missing `;' after regexp");
     57 		    get_next_token(); /* ; */
     58 		    if (sym->re)
     59 			Scanner_fatal(in, "sym already defined");
     60 		    sym->re = re;
     61 		    break;
     62 		}
     63 		/*@fallthrough@*/
     64 	    default:
     65 		/* rule: expr [/ expr] CODE */
     66 		re = parse_expr();
     67 		if (!re)
     68 		    Scanner_fatal(in, "expression syntax error");
     69 
     70 		if (curtok == '/') {
     71 		    get_next_token(); /* / */
     72 		    look = parse_expr();
     73 		} else
     74 		    look = RegExp_new_NullOp();
     75 
     76 		if (curtok != CODE)
     77 		    Scanner_fatal(in, "missing code after regexp");
     78 		re = RegExp_new_RuleOp(re, look, yylval.token, accept++);
     79 		get_next_token(); /* CODE */
     80 		spec = spec ? mkAlt(spec, re) : re;
     81 	}
     82     }
     83 }
     84 
     85 static RegExp *
     86 parse_expr(void)
     87 {
     88     RegExp *e, *f;
     89     e = parse_diff();
     90     while (curtok == '|') {
     91 	get_next_token(); /* | */
     92 	f = parse_diff();
     93 	e = mkAlt(e, f);
     94     }
     95     return e;
     96 }
     97 
     98 static RegExp *
     99 parse_diff(void)
    100 {
    101     RegExp *e, *f;
    102     e = parse_term();
    103     while (curtok == '\\') {
    104 	get_next_token(); /* \ */
    105 	f = parse_term();
    106 	e = mkDiff(e, f);
    107 	if(!e)
    108 	    Scanner_fatal(in, "can only difference char sets");
    109     }
    110     return e;
    111 }
    112 
    113 static RegExp *
    114 parse_term(void)
    115 {
    116     RegExp *e, *f;
    117     e = parse_factor();
    118     while ((f = parse_factor())) {
    119 	e = RegExp_new_CatOp(e, f);
    120     }
    121     return e;
    122 }
    123 
    124 static RegExp *
    125 parse_factor(void)
    126 {
    127     RegExp *e;
    128     char ch;
    129     e = parse_primary();
    130     while (curtok == CLOSE || curtok == CLOSESIZE) {
    131 	switch (curtok) {
    132 	    case CLOSE:
    133 		ch = yylval.op;
    134 		while (get_next_token() == CLOSE) {
    135 		    if (ch != yylval.op)
    136 			ch = '*';
    137 		}
    138 		switch (ch) {
    139 		    case '*':
    140 			e = mkAlt(RegExp_new_CloseOp(e), RegExp_new_NullOp());
    141 			break;
    142 		    case '+':
    143 			e = RegExp_new_CloseOp(e);
    144 			break;
    145 		    case '?':
    146 			e = mkAlt(e, RegExp_new_NullOp());
    147 			break;
    148 		}
    149 		break;
    150 	    case CLOSESIZE:
    151 		e = RegExp_new_CloseVOp(e, yylval.extop.minsize,
    152 					yylval.extop.maxsize);
    153 		get_next_token();	/* CLOSESIZE */
    154 		break;
    155 	    default:
    156 		Scanner_fatal(in, "parse error");
    157 		break;
    158 	}
    159     }
    160     return e;
    161 }
    162 
    163 static RegExp *
    164 parse_primary(void)
    165 {
    166     RegExp *e;
    167     switch (curtok) {
    168 	case ID:
    169 	    if (!yylval.symbol->re)
    170 		Scanner_fatal(in, "can't find symbol");
    171 	    e = yylval.symbol->re;
    172 	    get_next_token();
    173 	    break;
    174 	case RANGE:
    175 	case STRING:
    176 	    e = yylval.regexp;
    177 	    get_next_token();
    178 	    break;
    179 	case '(':
    180 	    get_next_token();
    181 	    e = parse_expr();
    182 	    if (curtok != ')')
    183 		Scanner_fatal(in, "missing closing parenthesis");
    184 	    get_next_token();
    185 	    break;
    186 	default:
    187 	    return NULL;
    188     }
    189     return e;
    190 }
    191 
    192 int
    193 yylex(void)
    194 {
    195     if (peektok != NONE) {
    196 	int tok = peektok;
    197 	yylval = peekval;
    198 	peektok = NONE;
    199 	return tok;
    200     }
    201     return Scanner_scan(in);
    202 }
    203 
    204 void line_source(FILE *o, unsigned int line)
    205 {
    206     char *	fnamebuf;
    207     char *	token;
    208 
    209     if (iFlag)
    210 	return;
    211     fprintf(o, "#line %u \"", line);
    212     if( fileName != NULL ) {
    213     	fnamebuf = mystrdup( fileName );
    214     } else {
    215 	fnamebuf = mystrdup( "<stdin>" );
    216     }
    217     token = strtok( fnamebuf, "\\" );
    218     for(;;) {
    219 	fprintf(o, "%s", token);
    220 	token = strtok( NULL, "\\" );
    221 	if( token == NULL ) break;
    222 	fputs("\\\\", o);
    223     }
    224     fputs("\"\n", o); oline++;
    225     free( fnamebuf );
    226 }
    227 
    228 void parse(FILE *i, FILE *o){
    229     time_t now;
    230 
    231     time(&now);
    232 
    233     peektok = NONE;
    234 
    235     fputs("/* Generated by re2c 0.9.1-C on ", o);
    236     fprintf(o, "%-24s", ctime(&now));
    237     fputs(" */\n", o); oline+=2;
    238 
    239     in = Scanner_new(i);
    240 
    241     line_source(o, Scanner_line(in));
    242 
    243     while(Scanner_echo(in, o)){
    244 	yyparse();
    245 	if(spec)
    246 	    genCode(o, spec);
    247 	line_source(o, Scanner_line(in));
    248     }
    249 }
    250