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 9int yylex(void); 10static RegExp *parse_expr(void); 11static RegExp *parse_diff(void); 12static RegExp *parse_term(void); 13static RegExp *parse_factor(void); 14static RegExp *parse_primary(void); 15 16static unsigned int accept; 17static RegExp *spec; 18static Scanner *in; 19 20static int curtok, peektok; 21yystype yylval; 22static yystype peekval; 23 24#define get_next_token() (curtok = yylex()) 25 26static void 27get_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 37static void 38yyparse(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 85static RegExp * 86parse_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 98static RegExp * 99parse_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 113static RegExp * 114parse_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 124static RegExp * 125parse_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 163static RegExp * 164parse_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 192int 193yylex(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 204void 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 228void 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