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