source: other-projects/rsyntax-textarea/devel-packages/jflex-1.4.3/src/JFlex/LexParse.cup@ 25584

Last change on this file since 25584 was 25584, checked in by davidb, 12 years ago

Initial cut an a text edit area for GLI that supports color syntax highlighting

File size: 23.6 KB
Line 
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * JFlex 1.4.3 *
3 * Copyright (C) 1998-2009 Gerwin Klein <[email protected]> *
4 * All rights reserved. *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License. See the file *
8 * COPYRIGHT for more information. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License along *
16 * with this program; if not, write to the Free Software Foundation, Inc., *
17 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
18 * *
19 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20
21package JFlex;
22
23import java.util.*;
24
25/* customizing code */
26
27action code {:
28
29 LexScan scanner;
30 CharClasses charClasses = new CharClasses(Options.jlex ? 127 : 0xFFFF);
31 RegExps regExps = new RegExps();
32 Macros macros = new Macros();
33 Integer stateNumber;
34 Timer t = new Timer();
35 EOFActions eofActions = new EOFActions();
36
37 void fatalError(ErrorMessages message, int line, int col) {
38 syntaxError(message, line, col);
39 throw new GeneratorException();
40 }
41
42 void fatalError(ErrorMessages message) {
43 fatalError(message, scanner.currentLine(), -1);
44 throw new GeneratorException();
45 }
46
47 void syntaxError(ErrorMessages message) {
48 Out.error(scanner.file, message, scanner.currentLine(), -1);
49 }
50
51 void syntaxError(ErrorMessages message, int line) {
52 Out.error(scanner.file, message, line, -1);
53 }
54
55 void syntaxError(ErrorMessages message, int line, int col) {
56 Out.error(scanner.file, message, line, col);
57 }
58
59
60 private boolean check(int type, char c) {
61 switch (type) {
62 case sym.JLETTERCLASS:
63 return Character.isJavaIdentifierStart(c);
64
65 case sym.JLETTERDIGITCLASS:
66 return Character.isJavaIdentifierPart(c);
67
68 case sym.LETTERCLASS:
69 return Character.isLetter(c);
70
71 case sym.DIGITCLASS:
72 return Character.isDigit(c);
73
74 case sym.UPPERCLASS:
75 return Character.isUpperCase(c);
76
77 case sym.LOWERCLASS:
78 return Character.isLowerCase(c);
79
80 default: return false;
81 }
82 }
83
84 private Vector makePreClass(int type) {
85
86 Vector result = new Vector();
87
88 char c = 0;
89 char start = 0;
90 char last = charClasses.getMaxCharCode();
91
92 boolean prev, current;
93
94 prev = check(type,'\u0000');
95
96 for (c = 1; c < last; c++) {
97
98 current = check(type,c);
99
100 if (!prev && current) start = c;
101 if (prev && !current) {
102 result.addElement(new Interval(start, (char)(c-1)));
103 }
104
105 prev = current;
106 }
107
108 // the last iteration is moved out of the loop to
109 // avoid an endless loop if last == maxCharCode and
110 // last+1 == 0
111 current = check(type,c);
112
113 if (!prev && current) result.addElement(new Interval(c,c));
114 if (prev && current) result.addElement(new Interval(start, c));
115 if (prev && !current) result.addElement(new Interval(start, (char)(c-1)));
116
117 return result;
118 }
119
120 private RegExp makeRepeat(RegExp r, int n1, int n2, int line, int col) {
121
122 if (n1 <= 0 && n2 <= 0) {
123 syntaxError(ErrorMessages.REPEAT_ZERO, line, col);
124 return null;
125 }
126
127 if (n1 > n2) {
128 syntaxError(ErrorMessages.REPEAT_GREATER, line, col);
129 return null;
130 }
131
132 int i;
133 RegExp result;
134
135 if (n1 > 0) {
136 result = r;
137 n1--; n2--; // we need one concatenation less than the number of expressions to match
138 }
139 else {
140 result = new RegExp1(sym.QUESTION,r);
141 n2--;
142 }
143
144 for (i = 0; i < n1; i++)
145 result = new RegExp2(sym.CONCAT, result, r);
146
147 n2-= n1;
148 for (i = 0; i < n2; i++)
149 result = new RegExp2(sym.CONCAT, result, new RegExp1(sym.QUESTION,r));
150
151 return result;
152 }
153
154 private RegExp makeNL() {
155 Vector list = new Vector();
156 list.addElement(new Interval('\n','\r'));
157 list.addElement(new Interval('\u0085','\u0085'));
158 list.addElement(new Interval('\u2028','\u2029'));
159
160 // assumption: line feeds are caseless
161 charClasses.makeClass(list, false);
162 charClasses.makeClass('\n', false);
163 charClasses.makeClass('\r', false);
164
165 RegExp1 c = new RegExp1(sym.CCLASS, list);
166 Character n = new Character('\n');
167 Character r = new Character('\r');
168
169 return new RegExp2(sym.BAR,
170 c,
171 new RegExp2(sym.CONCAT,
172 new RegExp1(sym.CHAR, r),
173 new RegExp1(sym.CHAR, n)));
174 }
175
176:};
177
178parser code {:
179 public LexScan scanner;
180
181 public LexParse(LexScan scanner) {
182 super(scanner);
183 this.scanner = scanner;
184 }
185
186 public CharClasses getCharClasses() {
187 return action_obj.charClasses;
188 }
189
190 public EOFActions getEOFActions() {
191 return action_obj.eofActions;
192 }
193
194 public void report_error(String message, Object info) {
195 if ( info instanceof java_cup.runtime.Symbol ) {
196 java_cup.runtime.Symbol s = (java_cup.runtime.Symbol) info;
197
198 if (s.sym == sym.EOF)
199 Out.error(ErrorMessages.UNEXPECTED_EOF);
200 else
201 Out.error(scanner.file, ErrorMessages.SYNTAX_ERROR, s.left, s.right);
202 }
203 else
204 Out.error(ErrorMessages.UNKNOWN_SYNTAX);
205 }
206
207 public void report_fatal_error(String message, Object info) {
208 // report_error(message, info);
209 throw new GeneratorException();
210 }
211
212:};
213
214init with {:
215 action_obj.scanner = this.scanner;
216:};
217
218/* token declarations */
219
220terminal OPENBRACKET, CLOSEBRACKET, HAT, DOLLAR, OPENCLASS,
221 CLOSECLASS, DASH, DELIMITER, EQUALS, COMMA, LESSTHAN,
222 MORETHAN, LBRACE, RBRACE, ASCII, FULL, UNICODE, REGEXPEND;
223
224terminal JLETTERCLASS, JLETTERDIGITCLASS, LETTERCLASS, DIGITCLASS,
225 UPPERCLASS, LOWERCLASS, EOFRULE, NOACTION, LOOKAHEAD;
226
227terminal Action ACTION;
228terminal String IDENT, USERCODE;
229terminal Integer REPEAT;
230
231/* tokens used in RegExp parse tree */
232terminal STAR, PLUS, BAR, QUESTION, POINT, BANG, TILDE;
233
234terminal Character CHAR;
235terminal String STRING, MACROUSE;
236
237/* symbols *only* used in the parse tree (not in the grammar) */
238terminal CCLASS, CCLASSNOT, CONCAT;
239terminal STRING_I, CHAR_I; /* case insensitive strings/chars */
240
241
242non terminal macros, macro;
243non terminal Integer rule;
244non terminal NFA specification;
245non terminal RegExp series, concs, nregexp, regexp, charclass, lookahead;
246non terminal Interval classcontentelem;
247non terminal Vector states, statesOPT, classcontent, preclass, rules;
248non terminal Boolean hatOPT;
249non terminal Action act, actions;
250
251
252/* grammar specification */
253start with specification;
254
255specification ::= USERCODE
256 /* delimiter is checked in lexer */
257 macros
258 DELIMITER
259 rules
260 {:
261 scanner.t.stop();
262
263 Out.checkErrors();
264
265 Out.time(ErrorMessages.PARSING_TOOK, t);
266
267 macros.expand();
268 Enumeration unused = macros.unused();
269 while ( unused.hasMoreElements() ) {
270 Out.warning("Macro \""+unused.nextElement()+"\" has been declared but never used.");
271 }
272
273 SemCheck.check(regExps, macros, scanner.file);
274
275 regExps.checkActions();
276 regExps.checkLookAheads();
277
278 Out.checkErrors();
279
280 if (Options.dump) charClasses.dump();
281
282 Out.print("Constructing NFA : ");
283
284 t.start();
285 int num = regExps.getNum();
286
287 RESULT = new NFA(charClasses.getNumClasses(),
288 scanner, regExps, macros, charClasses);
289
290 eofActions.setNumLexStates(scanner.states.number());
291
292 for (int i = 0; i < num; i++) {
293 if (regExps.isEOF(i))
294 eofActions.add( regExps.getStates(i), regExps.getAction(i) );
295 else
296 RESULT.addRegExp(i);
297 }
298
299 if (scanner.standalone) RESULT.addStandaloneRule();
300 t.stop();
301
302 Out.time("");
303 Out.time(ErrorMessages.NFA_TOOK, t);
304
305 :}
306 | /* emtpy spec. error */
307 {:
308 fatalError(ErrorMessages.NO_LEX_SPEC);
309 :}
310 ;
311
312macros ::= /* empty, most switches & state declarations are parsed in lexer */
313 | macros macro
314 | error;
315
316macro ::= ASCII
317 {: charClasses.setMaxCharCode(127); :}
318 | FULL
319 {: charClasses.setMaxCharCode(255); :}
320 | UNICODE
321 {: charClasses.setMaxCharCode(0xFFFF); :}
322 | IDENT:name EQUALS series:definition REGEXPEND
323 {: macros.insert(name, definition); :}
324 | IDENT EQUALS:e
325 {: syntaxError(ErrorMessages.REGEXP_EXPECTED, eleft, eright); :}
326 ;
327
328
329rules ::= rules:rlist rule:r
330 {: rlist.addElement(r); RESULT = rlist; :}
331 | rules:rlist1 LESSTHAN states:states MORETHAN LBRACE rules:rlist2 RBRACE
332 {:
333 Enumeration rs = rlist2.elements();
334 while ( rs.hasMoreElements() ) {
335 Integer elem = (Integer) rs.nextElement();
336 // might be null for error case of "rule"
337 if (elem != null) {
338 regExps.addStates( elem.intValue(), states );
339 }
340 rlist1.addElement( elem );
341 }
342 RESULT = rlist1;
343 :}
344 | LESSTHAN states:states MORETHAN LBRACE rules:rlist RBRACE
345 {:
346 Enumeration rs = rlist.elements();
347 while ( rs.hasMoreElements() ) {
348 Integer elem = (Integer) rs.nextElement();
349 // might be null for error case of "rule"
350 if (elem != null) {
351 regExps.addStates( elem.intValue(), states );
352 }
353 }
354 RESULT = rlist;
355 :}
356 | rule:r
357 {: RESULT = new Vector(); RESULT.addElement(r); :}
358 ;
359
360rule ::= statesOPT:s hatOPT:bol series:r actions:a
361 {: RESULT = new Integer(regExps.insert(rleft, s, r, a, bol, null)); :}
362 | statesOPT:s hatOPT:bol series:r lookahead:l act:a
363 {: RESULT = new Integer(regExps.insert(rleft, s, r, a, bol, l)); :}
364 | statesOPT:s hatOPT:bol series:r lookahead:l NOACTION:a
365 {: syntaxError(ErrorMessages.LOOKAHEAD_NEEDS_ACTION, aleft, aright+1); :}
366 | statesOPT:s EOFRULE ACTION:a
367 {: RESULT = new Integer(regExps.insert(s, a)); :}
368 | error
369 ;
370
371lookahead ::= DOLLAR
372 {: RESULT = makeNL(); :}
373 | LOOKAHEAD series:r
374 {: RESULT = r; :}
375 | LOOKAHEAD series:s DOLLAR
376 {: RESULT = new RegExp2(sym.CONCAT, s, makeNL()); :}
377 ;
378
379act ::= REGEXPEND ACTION:a
380 {: RESULT = a; :}
381 ;
382
383actions ::= act:a
384 {: RESULT = a; :}
385 | NOACTION
386 ;
387
388
389statesOPT ::= LESSTHAN states:list MORETHAN
390 {: RESULT = list; :}
391 | /* empty */
392 {: RESULT = new Vector(); :}
393 ;
394
395states ::= IDENT:id COMMA states:list
396 {:
397 stateNumber = scanner.states.getNumber( id );
398 if ( stateNumber != null )
399 list.addElement( stateNumber );
400 else {
401 throw new ScannerException(scanner.file, ErrorMessages.LEXSTATE_UNDECL,
402 idleft, idright);
403 }
404 RESULT = list;
405 :}
406 | IDENT:id
407 {:
408 Vector list = new Vector();
409 stateNumber = scanner.states.getNumber( id );
410 if ( stateNumber != null )
411 list.addElement( stateNumber );
412 else {
413 throw new ScannerException(scanner.file, ErrorMessages.LEXSTATE_UNDECL,
414 idleft, idright);
415 }
416 RESULT = list;
417 :}
418 | IDENT COMMA:c
419 {: syntaxError(ErrorMessages.REGEXP_EXPECTED, cleft, cright+1); :}
420 ;
421
422hatOPT ::= HAT
423 {: // assumption: there is no upper case for \n
424 charClasses.makeClass('\n', false);
425 RESULT = new Boolean(true); :}
426 | /* empty */
427 {: RESULT = new Boolean(false); :}
428 ;
429
430series ::= series:r1 BAR concs:r2
431 {: RESULT = new RegExp2(sym.BAR, r1, r2); :}
432 | concs:r
433 {: RESULT = r; :}
434 | BAR:b
435 {: syntaxError(ErrorMessages.REGEXP_EXPECTED, bleft, bright); :}
436 ;
437
438concs ::= concs:r1 nregexp:r2
439 {: RESULT = new RegExp2(sym.CONCAT, r1, r2); :}
440 | nregexp:r
441 {: RESULT = r; :}
442 ;
443
444nregexp ::= regexp:r
445 {: RESULT = r; :}
446 | BANG nregexp:r
447 {: RESULT = new RegExp1(sym.BANG, r); :}
448 | TILDE nregexp:r
449 {: RESULT = new RegExp1(sym.TILDE, r); :}
450 ;
451
452regexp ::= regexp:r STAR
453 {: RESULT = new RegExp1(sym.STAR, r); :}
454 | regexp:r PLUS
455 {: RESULT = new RegExp1(sym.PLUS, r); :}
456 | regexp:r QUESTION
457 {: RESULT = new RegExp1(sym.QUESTION, r); :}
458 | regexp:r REPEAT:n RBRACE:b
459 {: RESULT = makeRepeat(r, n.intValue(), n.intValue(), bleft, bright); :}
460 | regexp:r REPEAT:n1 REPEAT:n2 RBRACE
461 {: RESULT = makeRepeat(r, n1.intValue(), n2.intValue(), n1left, n2right); :}
462 | OPENBRACKET series:r CLOSEBRACKET
463 {: RESULT = r; :}
464 | MACROUSE:ident
465 {:
466 if ( !scanner.macroDefinition ) {
467 if ( ! macros.markUsed(ident) )
468 throw new ScannerException(scanner.file, ErrorMessages.MACRO_UNDECL,
469 identleft, identright);
470 }
471 RESULT = new RegExp1(sym.MACROUSE, ident);
472 :}
473 | charclass:c
474 {: RESULT = c; :}
475 | preclass:list
476 {:
477 try {
478 // assumption [correct?]: preclasses are already closed under case
479 charClasses.makeClass(list, false);
480 }
481 catch (CharClassException e) {
482 syntaxError(ErrorMessages.CHARSET_2_SMALL, listleft);
483 }
484 RESULT = new RegExp1(sym.CCLASS, list);
485 :}
486 | STRING:str
487 {:
488 try {
489 if ( scanner.caseless ) {
490 charClasses.makeClass(str, true);
491 RESULT = new RegExp1(sym.STRING_I, str);
492 }
493 else {
494 charClasses.makeClass(str, false);
495 RESULT = new RegExp1(sym.STRING, str);
496 }
497 }
498 catch (CharClassException e) {
499 syntaxError(ErrorMessages.CS2SMALL_STRING, strleft, strright);
500 }
501
502 :}
503 | POINT
504 {:
505 Vector any = new Vector();
506 any.addElement(new Interval('\n','\n'));
507 // assumption: there is no upper case for \n
508 charClasses.makeClass('\n', false);
509 RESULT = new RegExp1(sym.CCLASSNOT, any);
510 :}
511 | CHAR:c
512 {:
513 try {
514 if ( scanner.caseless ) {
515 charClasses.makeClass(c.charValue(), true);
516 RESULT = new RegExp1(sym.CHAR_I, c);
517 }
518 else {
519 charClasses.makeClass(c.charValue(), false);
520 RESULT = new RegExp1(sym.CHAR, c);
521 }
522 }
523 catch (CharClassException e) {
524 syntaxError(ErrorMessages.CS2SMALL_CHAR, cleft, cright);
525 }
526 :}
527 ;
528
529charclass ::= OPENCLASS CLOSECLASS
530 {:
531 RESULT = new RegExp1(sym.CCLASS,null);
532 :}
533 | OPENCLASS classcontent:list CLOSECLASS:close
534 {:
535 try {
536 charClasses.makeClass(list, Options.jlex && scanner.caseless);
537 }
538 catch (CharClassException e) {
539 syntaxError(ErrorMessages.CHARSET_2_SMALL, closeleft, closeright);
540 }
541 RESULT = new RegExp1(sym.CCLASS,list);
542 :}
543 | OPENCLASS HAT CLOSECLASS:close
544 {:
545 Vector list = new Vector();
546 list.addElement(new Interval((char)0,CharClasses.maxChar));
547 try {
548 charClasses.makeClass(list, false);
549 }
550 catch (CharClassException e) {
551 syntaxError(ErrorMessages.CHARSET_2_SMALL, closeleft, closeright);
552 }
553 RESULT = new RegExp1(sym.CCLASS,list);
554 :}
555 | OPENCLASS HAT classcontent:list CLOSECLASS:close
556 {:
557 try {
558 charClasses.makeClassNot(list, Options.jlex && scanner.caseless);
559 }
560 catch (CharClassException e) {
561 syntaxError(ErrorMessages.CHARSET_2_SMALL, closeleft, closeright);
562 }
563 RESULT = new RegExp1(sym.CCLASSNOT,list);
564 :}
565 | OPENCLASS DASH classcontent:list CLOSECLASS:close
566 {:
567 try {
568 list.addElement(new Interval('-','-'));
569 charClasses.makeClass(list, Options.jlex && scanner.caseless);
570 }
571 catch (CharClassException e) {
572 syntaxError(ErrorMessages.CHARSET_2_SMALL, closeleft, closeright);
573 }
574 RESULT = new RegExp1(sym.CCLASS,list);
575 :}
576 | OPENCLASS HAT DASH classcontent:list CLOSECLASS:close
577 {:
578 try {
579 list.addElement(new Interval('-','-'));
580 charClasses.makeClassNot(list, Options.jlex && scanner.caseless);
581 }
582 catch (CharClassException e) {
583 syntaxError(ErrorMessages.CHARSET_2_SMALL, closeleft, closeright);
584 }
585 RESULT = new RegExp1(sym.CCLASSNOT,list);
586 :}
587 ;
588
589classcontent ::= classcontent:list classcontentelem:elem
590 {:
591 list.addElement(elem);
592 RESULT = list;
593 :}
594 | classcontentelem:elem
595 {:
596 Vector list = new Vector();
597 list.addElement(elem);
598 RESULT = list;
599 :}
600 | classcontent:list preclass:plist
601 {:
602 for (Enumeration e = plist.elements(); e.hasMoreElements();)
603 list.addElement(e.nextElement());
604 RESULT = list;
605 :}
606 | preclass:list
607 {: RESULT = list; :}
608 | classcontent:list STRING:s
609 {:
610 for (int i = 0; i < s.length(); i++)
611 list.addElement(new Interval(s.charAt(i),s.charAt(i)));
612 RESULT = list;
613 :}
614 | STRING:s
615 {:
616 RESULT = new Vector();
617 for (int i = 0; i < s.length(); i++)
618 RESULT.addElement(new Interval(s.charAt(i),s.charAt(i)));
619 :}
620 | classcontent:list MACROUSE:ident
621 {:
622 syntaxError(ErrorMessages.CHARCLASS_MACRO, identleft, identright);
623 :}
624 | MACROUSE:ident
625 {:
626 syntaxError(ErrorMessages.CHARCLASS_MACRO, identleft, identright);
627 :}
628 ;
629
630classcontentelem ::= CHAR:c1 DASH CHAR:c2
631 {: RESULT = new Interval(c1.charValue(), c2.charValue()); :}
632 | CHAR:c
633 {: RESULT = new Interval(c.charValue(), c.charValue()); :}
634 ;
635
636preclass ::= JLETTERCLASS
637 {: RESULT = makePreClass(sym.JLETTERCLASS); :}
638 | JLETTERDIGITCLASS
639 {: RESULT = makePreClass(sym.JLETTERDIGITCLASS); :}
640 | LETTERCLASS
641 {: RESULT = makePreClass(sym.LETTERCLASS); :}
642 | DIGITCLASS
643 {: RESULT = makePreClass(sym.DIGITCLASS); :}
644 | UPPERCLASS
645 {: RESULT = makePreClass(sym.UPPERCLASS); :}
646 | LOWERCLASS
647 {: RESULT = makePreClass(sym.LOWERCLASS); :}
648 ;
Note: See TracBrowser for help on using the repository browser.