1 ///////////////////////////////////////////////////////////////////////////////
2 // This file is generated automatically using Prop (version 2.3.6),
3 // last updated on Nov 2, 1999.
4 // The original source file is "lexeme.pcc".
5 ///////////////////////////////////////////////////////////////////////////////
8 ///////////////////////////////////////////////////////////////////////////////
10 // This file implements some support routines for lexeme and regular
11 // expressions handling.
13 ///////////////////////////////////////////////////////////////////////////////
15 #include <AD/strings/charesc.h>
22 ///////////////////////////////////////////////////////////////////////////////
23 // Properly quote a string
24 ///////////////////////////////////////////////////////////////////////////////
25 const char * make_quoted_string (const char * s
)
26 { char * new_str
= str_pool
[strlen(s
) * 4];
28 char * end_str
= quote_string(new_str
+1,s
);
34 ///////////////////////////////////////////////////////////////////////////////
35 // Add contexts to a string/regexp pattern
36 ///////////////////////////////////////////////////////////////////////////////
37 Pat
add_contexts (Conses contexts
, Pat pat
)
51 case a_Pat::tag_LITERALpat
: {
52 switch (((Pat_LITERALpat
*)pat
)->LITERALpat
->tag__
) {
53 case a_Literal::tag_STRINGlit
: {
55 return add_contexts(contexts
,LITERALpat(REGEXPlit(convert_regexp(((Literal_STRINGlit
*)((Pat_LITERALpat
*)pat
)->LITERALpat
)->STRINGlit
))));
59 case a_Literal::tag_REGEXPlit
: {
63 *p
++ = '/'; *p
++ = '<';
64 for (Conses l
= contexts
; l
; l
= l
->_2
)
65 { if (l
->_1
) strcpy(p
,l
->_1
->name
);
67 if (l
->_2
) *p
++ = ',';
70 strcpy(p
,((Literal_REGEXPlit
*)((Pat_LITERALpat
*)pat
)->LITERALpat
)->REGEXPlit
+1); p
+= strlen(p
) - 1;
72 debug_msg("converting %p into %s\n",
73 CONTEXTpat(contexts
,pat
), buffer
);
74 Pat new_pat
= LITERALpat(REGEXPlit(str_pool
[buffer
]));
75 new_pat
->selector
= pat
->selector
;
76 new_pat
->ty
= pat
->ty
;
84 error("%Lillegal context(s) in pattern %p\n",
85 CONTEXTpat(contexts
,pat
));
92 case a_Pat::tag_LEXEMEpat
: {
94 Pat this_pat
= expand_lexeme_pat(pat
,((Pat_LEXEMEpat
*)pat
)->_2
,((Pat_LEXEMEpat
*)pat
)->_3
,((Pat_LEXEMEpat
*)pat
)->_4
);
102 switch (this_pat
->tag__
) {
103 case a_Pat::tag_LOGICALpat
: {
104 switch (((Pat_LOGICALpat
*)this_pat
)->_1
) {
106 #line 60 "lexeme.pcc"
107 Pat one_pat
= add_contexts(contexts
,((Pat_LOGICALpat
*)this_pat
)->_3
);
108 new_pat
= new_pat
== NOpat
? one_pat
109 : LOGICALpat(ORpat
,one_pat
,new_pat
);
110 this_pat
= ((Pat_LOGICALpat
*)this_pat
)->_2
;
112 #line 64 "lexeme.pcc"
114 default: { goto L2
; } break;
117 default: { goto L2
; } break;
123 #line 65 "lexeme.pcc"
124 #line 65 "lexeme.pcc"
126 Pat p
= add_contexts(contexts
,this_pat
);
127 new_pat
= new_pat
== NOpat
? p
: LOGICALpat(ORpat
,p
,new_pat
);
130 #line 69 "lexeme.pcc"
132 default: { goto L1
; } break;
136 #line 75 "lexeme.pcc"
137 #line 75 "lexeme.pcc"
141 ///////////////////////////////////////////////////////////////////////////////
142 // Convert a string pattern into a regexp pattern if necessary
143 ///////////////////////////////////////////////////////////////////////////////
144 #line 81 "lexeme.pcc"
145 #line 85 "lexeme.pcc"
146 Pat
convert_regexp (Pat x_1
);
147 Pat
convert_regexp (Pat x_1
)
150 switch (x_1
->tag__
) {
151 case a_Pat::tag_LITERALpat
: {
152 switch (((Pat_LITERALpat
*)x_1
)->LITERALpat
->tag__
) {
153 case a_Literal::tag_STRINGlit
: {
154 #line 82 "lexeme.pcc"
155 return LITERALpat(REGEXPlit(convert_regexp(((Literal_STRINGlit
*)((Pat_LITERALpat
*)x_1
)->LITERALpat
)->STRINGlit
)));
156 #line 82 "lexeme.pcc"
160 #line 84 "lexeme.pcc"
162 #line 84 "lexeme.pcc"
166 default: { goto L3
; } break;
170 #line 85 "lexeme.pcc"
171 #line 85 "lexeme.pcc"
174 ///////////////////////////////////////////////////////////////////////////////
175 // Convert a string literal into a regular expression literal.
176 ///////////////////////////////////////////////////////////////////////////////
177 const char * convert_regexp (const char * string
, Bool quotes
)
179 register char * p
= buf
;
180 register const char * s
= string
+ 1;
181 if (quotes
) *p
++ = '/';
186 #line 98 "lexeme.pcc"
187 #line 103 "lexeme.pcc"
208 #line 102 "lexeme.pcc"
209 *p
++ = '\\'; *p
++ = c
;
210 #line 102 "lexeme.pcc"
213 #line 103 "lexeme.pcc"
215 #line 103 "lexeme.pcc"
219 #line 104 "lexeme.pcc"
220 #line 104 "lexeme.pcc"
224 if (quotes
) *p
++ = '/';
226 debug_msg("converting %s into %s\n", string
, buf
);
227 return str_pool
[buf
];
230 ///////////////////////////////////////////////////////////////////////////////
231 // The global lexeme and lexeme class environments
232 ///////////////////////////////////////////////////////////////////////////////
233 static HashTable
lexeme_env(string_hash
, string_equal
);
234 static HashTable
lexeme_class_env(string_hash
, string_equal
);
236 ///////////////////////////////////////////////////////////////////////////////
237 // Method to update or lookup from the lexeme class environment
238 ///////////////////////////////////////////////////////////////////////////////
239 void update_lexeme_class (Id id
, TermDefs terms
)
240 { if (lexeme_class_env
.contains(id
))
241 { error ("%Lredefinition of lexeme class %s\n", id
); }
243 { lexeme_class_env
.insert(id
, terms
); }
246 TermDefs
lookup_lexeme_class (Id id
)
247 { HashTable::Entry
* e
= lexeme_class_env
.lookup(id
);
248 if (e
) return TermDefs(e
->v
);
249 else { error("%Llexeme class %s is undefined\n", id
); return
250 #line 132 "lexeme.pcc"
251 #line 132 "lexeme.pcc"
253 #line 132 "lexeme.pcc"
254 #line 132 "lexeme.pcc"
258 ///////////////////////////////////////////////////////////////////////////////
259 // Method to expand a pattern taking into account of lexeme definitions.
260 ///////////////////////////////////////////////////////////////////////////////
261 Pat
mk_regexp_pat(const char * re
)
262 { const char * p
= re
;
265 if (strchr(re
,'{') != 0)
269 { do { *q
++ = *p
; } while (*p
&& *p
++ != '>'); }
271 #line 147 "lexeme.pcc"
272 #line 189 "lexeme.pcc"
277 case '\000': { goto L5
; } break;
279 #line 148 "lexeme.pcc"
281 while (p
[-1] && (p
[-2] == '\\' || p
[-1] != ']'));
283 #line 150 "lexeme.pcc"
286 #line 151 "lexeme.pcc"
287 char name
[256]; char * r
;
288 for (r
= name
, p
++; *p
&& *p
!= '}';) *r
++ = *p
++;
290 else error ("%Lmissing '}' in regular expression %s\n",re
);
292 HashTable::Entry
* e
= lexeme_env
.lookup(name
);
294 { Pat pattern
= (Pat
)e
->v
;
296 #line 159 "lexeme.pcc"
297 #line 169 "lexeme.pcc"
300 switch (pattern
->tag__
) {
301 case a_Pat::tag_LITERALpat
: {
302 switch (((Pat_LITERALpat
*)pattern
)->LITERALpat
->tag__
) {
303 case a_Literal::tag_STRINGlit
: {
304 #line 165 "lexeme.pcc"
305 *q
++ = '('; strcpy(q
, convert_regexp(((Literal_STRINGlit
*)((Pat_LITERALpat
*)pattern
)->LITERALpat
)->STRINGlit
,false));
306 q
+= strlen(q
) - 1; *q
++ = ')';
308 #line 167 "lexeme.pcc"
310 case a_Literal::tag_REGEXPlit
: {
311 #line 161 "lexeme.pcc"
312 *q
++ = '('; strcpy(q
,((Literal_REGEXPlit
*)((Pat_LITERALpat
*)pattern
)->LITERALpat
)->REGEXPlit
+1); q
+= strlen(((Literal_REGEXPlit
*)((Pat_LITERALpat
*)pattern
)->LITERALpat
)->REGEXPlit
)-2;
315 #line 163 "lexeme.pcc"
321 default: { goto L6
; } break;
325 #line 169 "lexeme.pcc"
326 #line 169 "lexeme.pcc"
329 { error ("%Llexeme {%s} is undefined in %s\n", name
, re
);
332 #line 173 "lexeme.pcc"
335 #line 174 "lexeme.pcc"
337 const char * r
= parse_char(p
,ch
);
338 // if (*p == '\\') *q++ = '\\';
341 #line 178 "lexeme.pcc"
342 #line 184 "lexeme.pcc"
363 #line 182 "lexeme.pcc"
364 *q
++ = '\\'; *q
++ = ch
;
366 #line 183 "lexeme.pcc"
369 #line 184 "lexeme.pcc"
370 q
= print_char(q
,ch
);
371 #line 184 "lexeme.pcc"
375 #line 185 "lexeme.pcc"
376 #line 185 "lexeme.pcc"
379 { q
= print_char(q
,ch
); }
382 #line 189 "lexeme.pcc"
388 #line 190 "lexeme.pcc"
389 #line 190 "lexeme.pcc"
392 debug_msg("%s ==> %s\n", re
, buf
);
395 return LITERALpat(REGEXPlit(str_pool
[re
]));
398 ///////////////////////////////////////////////////////////////////////////////
399 // Method to update the lexeme environment.
400 ///////////////////////////////////////////////////////////////////////////////
401 void update_lexeme(Id id
, Ids args
, Pat pat
)
402 { HashTable::Entry
* e
= lexeme_env
.lookup(id
);
404 { error("%Llexeme {%s} already defined as %p\n",id
,(Pat
)e
->v
);
406 { lexeme_env
.insert(id
,pat
);
410 ///////////////////////////////////////////////////////////////////////////////
411 // Method to expand a lexeme pattern into a set of disjunctive patterns.
412 ///////////////////////////////////////////////////////////////////////////////
413 Pat
expand_lexeme_pat(Pat pat
, Ty ty
, int n
, Cons terms
[])
415 #line 214 "lexeme.pcc"
416 #line 237 "lexeme.pcc"
418 Ty _V2
= deref_all(ty
);
420 switch (_V2
->tag__
) {
421 case a_Ty::tag_TYCONty
: {
422 if (boxed(((Ty_TYCONty
*)_V2
)->_1
)) {
423 switch (((Ty_TYCONty
*)_V2
)->_1
->tag__
) {
424 case a_TyCon::tag_DATATYPEtycon
: {
426 #line 216 "lexeme.pcc"
427 ((((TyCon_DATATYPEtycon
*)((Ty_TYCONty
*)_V2
)->_1
)->qualifiers
| QUALlexeme
) == 0)
428 #line 216 "lexeme.pcc"
431 #line 217 "lexeme.pcc"
432 error ("%Ldatatype %T is not a lexeme type\n", ty
);
433 #line 217 "lexeme.pcc"
436 #line 219 "lexeme.pcc"
437 Pat disj_pats
= NOpat
;
438 for (int i
= 0; i
< n
; i
++)
440 #line 221 "lexeme.pcc"
441 #line 233 "lexeme.pcc"
445 if (_V3
->lexeme_pattern
) {
446 #line 223 "lexeme.pcc"
447 Pat new_pat
= subst(convert_regexp(_V3
->lexeme_pattern
),0,true);
448 disj_pats
= (disj_pats
== NOpat
) ? new_pat
449 : LOGICALpat(ORpat
,disj_pats
, new_pat
);
450 disj_pats
->selector
= pat
->selector
;
452 #line 227 "lexeme.pcc"
454 #line 229 "lexeme.pcc"
455 error ("%Llexeme pattern is undefined for constructor %s\n",
458 #line 231 "lexeme.pcc"
462 #line 233 "lexeme.pcc"
463 #line 233 "lexeme.pcc"
468 #line 236 "lexeme.pcc"
473 #line 237 "lexeme.pcc"
474 error ("%Lnon lexeme type %T in pattern %p\n", ty
, pat
);
475 #line 237 "lexeme.pcc"
480 default: { goto L8
; } break;
484 #line 238 "lexeme.pcc"
485 #line 238 "lexeme.pcc"
489 #line 241 "lexeme.pcc"
491 ------------------------------- Statistics -------------------------------
492 Merge matching rules = yes
493 Number of DFA nodes merged = 197
494 Number of ifs generated = 9
495 Number of switches generated = 13
498 Adaptive matching = enabled
499 Fast string matching = disabled
500 Inline downcasts = enabled
501 --------------------------------------------------------------------------